home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / tracer / trcfile.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  62KB  |  3,588 lines

  1.  
  2. static char rcsid[] = 
  3.     "$Id: trcfile.c,v 4.8 1997/05/27 15:53:34 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         Tracer version 1.0:  A Trace File Generator for PVM
  7.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  8.  *           Authors:  James Arthur Kohl and G. A. Geist
  9.  *                   (C) 1994 All Rights Reserved
  10.  *
  11.  *                              NOTICE
  12.  *
  13.  * Permission to use, copy, modify, and distribute this software and
  14.  * its documentation for any purpose and without fee is hereby granted
  15.  * provided that the above copyright notice appear in all copies and
  16.  * that both the copyright notice and this permission notice appear
  17.  * in supporting documentation.
  18.  *
  19.  * Neither the Institution, Oak Ridge National Laboratory, nor the
  20.  * Authors make any representations about the suitability of this
  21.  * software for any purpose.  This software is provided ``as is''
  22.  * without express or implied warranty.
  23.  *
  24.  * Tracer was funded by the U.S. Department of Energy.
  25.  */
  26.  
  27.  
  28. /* Tracer Library Header */
  29.  
  30. #include "trclib.h"
  31.  
  32.  
  33. /* Trace Lookup Trie Init Routines */
  34.  
  35. void
  36. trc_init_did_trie()
  37. {
  38.     TRC_DID dptr;
  39.  
  40.     int i;
  41.  
  42.     TRC_DID_TRIE = trc_create_triestack();
  43.  
  44.     for ( i=TEV_DID_FIRST ; i <= TEV_DID_MAX ; i++ )
  45.     {
  46.         dptr = trc_create_did();
  47.  
  48.         dptr->id = i;
  49.  
  50.         dptr->name = trc_copy_str( pvmtevdidlist[i].did );
  51.  
  52.         dptr->desc = trc_copy_str( pvmtevdidlist[i].desc );
  53.  
  54.         dptr->next = TRC_DID_LIST;
  55.  
  56.         TRC_DID_LIST = dptr;
  57.  
  58.         trc_add_to_trie( TRC_DID_TRIE, dptr->name, (void *) dptr );
  59.  
  60.         TRC_LOCAL_DID[i] = dptr;
  61.     }
  62. }
  63.  
  64.  
  65. /* Trace File Generation Routines */
  66.  
  67. void
  68. trc_set_didlist( H, D )
  69. TRC_HOST H;
  70. TRC_DID D;
  71. {
  72.     if ( H != NULL )
  73.     {
  74.         trc_check_listsize( &(H->didlist), &(H->didsize), D->id );
  75.  
  76.         H->didlist[ D->id ] = (void *) D;
  77.     }
  78.  
  79.     else
  80.         printf( "Error: No Host for TEV Semantic Identifier List\n" );
  81. }
  82.  
  83.  
  84. TRC_DID
  85. trc_get_did( H, id )
  86. TRC_HOST H;
  87. int id;
  88. {
  89.     TRC_DID D;
  90.  
  91.     D = (TRC_DID) NULL;
  92.  
  93.     /* Use Host Lookup */
  94.  
  95.     if ( H != NULL && H->didlist != NULL && id < H->didsize )
  96.         D = (TRC_DID) (H->didlist[ id ]);
  97.  
  98.     /* Use Default Local Lookup */
  99.  
  100.     else if ( id >= TEV_DID_FIRST && id <= TEV_DID_MAX )
  101.         D = TRC_LOCAL_DID[ id ];
  102.  
  103.     return( D );
  104. }
  105.  
  106.  
  107. int
  108. trc_add_tevdesc( ID, TDptr, tid, omit )
  109. TRC_ID ID;
  110. TRC_TEVDESC *TDptr;
  111. int tid;
  112. int omit;
  113. {
  114.     TRC_TEVDESC *newlist;
  115.  
  116.     TRC_TEVDESC tdptr;
  117.     TRC_TEVDESC last;
  118.  
  119.     int newsize;
  120.     int index;
  121.     int eid;
  122.     int i;
  123.  
  124.     /* Verify Descriptor List is Large Enough */
  125.  
  126.     eid = (*TDptr)->eid;
  127.  
  128.     if ( eid >= TRC_TEVDESC_SIZE )
  129.     {
  130.         newsize = 2 * ( eid + 1 );
  131.  
  132.         newlist = (TRC_TEVDESC *) malloc( (unsigned) newsize
  133.             * sizeof( TRC_TEVDESC ) );
  134.         trc_memcheck( newlist, "New TRC_TEVDESC Pointer List" );
  135.  
  136.         for ( i=0 ; i < TRC_TEVDESC_SIZE ; i++ )
  137.         {
  138.             newlist[i] = TRC_TEVDESC_LIST[i];
  139.  
  140.             TRC_TEVDESC_LIST[i] = (TRC_TEVDESC) NULL;
  141.         }
  142.  
  143.         for ( i=TRC_TEVDESC_SIZE ; i < newsize ; i++ )
  144.             newlist[i] = (TRC_TEVDESC) NULL;
  145.  
  146.         free( TRC_TEVDESC_LIST );
  147.  
  148.         TRC_TEVDESC_LIST = newlist;
  149.  
  150.         TRC_TEVDESC_SIZE = newsize;
  151.     }
  152.  
  153.     /* Search for Existing Descriptor */
  154.  
  155.     tdptr = TRC_TEVDESC_LIST[ eid ];
  156.  
  157.     last = (TRC_TEVDESC) NULL;
  158.  
  159.     index = 0;
  160.  
  161.     while ( tdptr != NULL )
  162.     {
  163.         if ( trc_cmp_tevdesc( *TDptr, tdptr ) )
  164.         {
  165.             if ( !omit && tdptr->dump && ID != NULL )
  166.                 trc_dump_tevdesc( ID, tdptr, tid );
  167.  
  168.             (*TDptr)->index = tdptr->index;
  169.  
  170.             if ( ID != NULL )
  171.                 trc_store_data_values( ID, *TDptr, tid, omit );
  172.  
  173.             trc_free_tevdesc( TDptr );
  174.  
  175.             *TDptr = tdptr;
  176.  
  177.             (tdptr->refcount)++;
  178.  
  179.             return( TRC_FALSE );
  180.         }
  181.  
  182.         index++;
  183.  
  184.         last = tdptr;
  185.  
  186.         tdptr = tdptr->next;
  187.     }
  188.  
  189.     /* Add New Descriptor */
  190.  
  191.     if ( last != NULL )
  192.         last->next = *TDptr;
  193.  
  194.     else
  195.         TRC_TEVDESC_LIST[ eid ] = *TDptr;
  196.  
  197.     (*TDptr)->index = index;
  198.  
  199.     if ( omit )
  200.         (*TDptr)->dump = TRC_FALSE;
  201.  
  202.     else
  203.         (*TDptr)->dump = TRC_TRUE;
  204.  
  205.     return( TRC_TRUE );
  206. }
  207.  
  208.  
  209. void
  210. trc_set_tevlist( TT, H, TD )
  211. TRC_TEVTASK TT;
  212. TRC_HOST H;
  213. TRC_TEVDESC TD;
  214. {
  215.     if ( TT != NULL )
  216.     {
  217.         trc_check_listsize( &(TT->tevlist), &(TT->tevsize),
  218.             TRC_TEVINDEX_OF( TD->eid, TRC_MAX_TEV ) );
  219.  
  220.         TT->tevlist[ TRC_TEVINDEX_OF( TD->eid, TD->entry_exit ) ] =
  221.             (void *) TD;
  222.     }
  223.  
  224.     else if ( H != NULL )
  225.     {
  226.         trc_check_listsize( &(H->tevlist), &(H->tevsize),
  227.             TRC_TEVINDEX_OF( TD->eid, TRC_MAX_TEV ) );
  228.  
  229.         H->tevlist[ TRC_TEVINDEX_OF( TD->eid, TD->entry_exit ) ] =
  230.             (void *) TD;
  231.     }
  232.  
  233.     else
  234.         printf( "Error: No Task or Host for TEV Index List\n" );
  235. }
  236.  
  237.  
  238. TRC_TEVDESC
  239. trc_get_tevdesc( TT, H, eid, entry_exit )
  240. TRC_TEVTASK TT;
  241. TRC_HOST H;
  242. int eid;
  243. int entry_exit;
  244. {
  245.     TRC_TEVDESC TD;
  246.  
  247.     if ( TT != NULL )
  248.     {
  249.         TD = (TRC_TEVDESC)
  250.             (TT->tevlist[ TRC_TEVINDEX_OF(eid,entry_exit) ]);
  251.     }
  252.  
  253.     else if ( H != NULL )
  254.     {
  255.         TD = (TRC_TEVDESC)
  256.             (H->tevlist[ TRC_TEVINDEX_OF(eid,entry_exit) ]);
  257.     }
  258.  
  259.     else
  260.         TD = (TRC_TEVDESC) NULL;
  261.  
  262.     return( TD );
  263. }
  264.  
  265.  
  266. void
  267. trc_dump_tevdesc( ID, TD, tid )
  268. TRC_ID ID;
  269. TRC_TEVDESC TD;
  270. int tid;
  271. {
  272.     TRC_DATADESC DD;
  273.  
  274.     TRC_DID D;
  275.  
  276.     int user_defined;
  277.     int dummy;
  278.  
  279.     if ( ID->event_dump_hdr )
  280.         (ID->event_dump_hdr)( ID, tid );
  281.  
  282.     fprintf( ID->trace_out, "\n" );
  283.  
  284.     if ( ID->event_dump_hdr )
  285.         (ID->event_dump_hdr)( ID, tid );
  286.  
  287.     if ( TD->index >= 0 )
  288.     {
  289.         fprintf( ID->trace_out, "#%d: \"%s(",  /* ) */
  290.             ( 1000 * ( TD->index + 1 ) ) + ( 2 * TD->eid )
  291.                 + ( ( TD->entry_exit == TRC_EXIT_TEV ) ? 1 : 0 ),
  292.             TD->name );
  293.  
  294.         if ( TD->entry_exit == TRC_ENTRY_TEV )
  295.             fprintf( ID->trace_out, "0." );
  296.  
  297.         else if ( TD->entry_exit == TRC_EXIT_TEV )
  298.             fprintf( ID->trace_out, "1." );
  299.  
  300.         fprintf( ID->trace_out, "%d", TD->index );
  301.  
  302.         fprintf( ID->trace_out, /* ( */ ")\"\n" );
  303.     }
  304.  
  305.     else
  306.         fprintf( ID->trace_out, "#%d: \"%s\"\n", TD->eid, TD->name );
  307.  
  308.     if ( ID->event_dump_hdr )
  309.         (ID->event_dump_hdr)( ID, tid );
  310.  
  311.     fprintf( ID->trace_out, "{\n" );
  312.  
  313.     if ( ID->event_dump_hdr )
  314.         (ID->event_dump_hdr)( ID, tid );
  315.  
  316.     /* Sneak in Task ID for User Defined Events */
  317.  
  318.     user_defined = !strcmp( TD->name, "user_defined" );
  319.  
  320.     if ( user_defined )
  321.     {
  322.         D = trc_get_did( (TRC_HOST) NULL, TEV_DID_TID );
  323.  
  324.         fprintf( ID->trace_out, "\t// \"%s\" \"%s\"\n",
  325.             D->name, D->desc );
  326.  
  327.         if ( ID->event_dump_hdr )
  328.             (ID->event_dump_hdr)( ID, tid );
  329.  
  330.         fprintf( ID->trace_out, "\t%s \"%s\";\n",
  331.             TRC_TYPE_STRS[ TEV_DATA_INT ], D->name );
  332.  
  333.         if ( ID->event_dump_hdr )
  334.             (ID->event_dump_hdr)( ID, tid );
  335.     }
  336.  
  337.     /* Dump (Remainder) of Descriptor */
  338.  
  339.     DD = TD->ddesc;
  340.  
  341.     dummy = 0;
  342.  
  343.     while ( DD != NULL )
  344.     {
  345.         if ( !user_defined || DD->did != NULL )
  346.         {
  347.             fprintf( ID->trace_out, "\t// \"%s\" \"%s\"\n",
  348.                 DD->did->name, DD->did->desc );
  349.         }
  350.  
  351.         else
  352.         {
  353.             fprintf( ID->trace_out,
  354.                 "\t// \"USR%d\" \"User Defined Value #%d\"\n",
  355.                 dummy, dummy );
  356.         }
  357.  
  358.         if ( ID->event_dump_hdr )
  359.             (ID->event_dump_hdr)( ID, tid );
  360.  
  361.         if ( !user_defined || DD->did != NULL )
  362.         {
  363.             fprintf( ID->trace_out, "\t%s \"%s\"",
  364.                 TRC_TYPE_STRS[ DD->dt ], DD->did->name );
  365.         }
  366.  
  367.         else
  368.         {
  369.             fprintf( ID->trace_out, "\t%s \"USR%d\"",
  370.                 TRC_TYPE_STRS[ DD->dt ], dummy );
  371.  
  372.             dummy++;
  373.         }
  374.  
  375.         if ( DD->array == TEV_DATA_ARRAY )
  376.             fprintf( ID->trace_out, "[]" );
  377.  
  378.         if ( DD->dt == TEV_DATA_STRING )
  379.             fprintf( ID->trace_out, "[]" );
  380.  
  381.         fprintf( ID->trace_out, ";\n" );
  382.  
  383.         if ( ID->event_dump_hdr )
  384.             (ID->event_dump_hdr)( ID, tid );
  385.  
  386.         DD = DD->next;
  387.     }
  388.  
  389.     fprintf( ID->trace_out, "};;\n" );
  390.  
  391.     if ( ID->event_dump_hdr )
  392.         (ID->event_dump_hdr)( ID, tid );
  393.  
  394.     fprintf( ID->trace_out, "\n" );
  395.  
  396.     TD->dump = TRC_FALSE;
  397. }
  398.  
  399.  
  400. void
  401. trc_check_listsize( list, size, index )
  402. void ***list;
  403. int *size;
  404. int index;
  405. {
  406.     void **newlist;
  407.  
  408.     int newsize;
  409.     int i;
  410.  
  411.     if ( index >= *size )
  412.     {
  413.         newsize = 2 * index;
  414.  
  415.         newsize = newsize ? newsize : 100;
  416.  
  417.         newlist = (void **) malloc( (unsigned) newsize
  418.             * sizeof(void *) );
  419.         trc_memcheck( newlist, "New TRC_TEVDESC Index List" );
  420.  
  421.         for ( i=0 ; i < *size ; i++ )
  422.         {
  423.             newlist[i] = (*list)[i];
  424.  
  425.             (*list)[i] = (void *) NULL;
  426.         }
  427.  
  428.         for ( i=(*size) ; i < newsize ; i++ )
  429.             newlist[i] = (void *) NULL;
  430.  
  431.         free( *list );
  432.  
  433.         *list = newlist;
  434.         *size = newsize;
  435.     }
  436. }
  437.  
  438.  
  439. void
  440. trc_store_event_header( ID, TD, tid )
  441. TRC_ID ID;
  442. TRC_TEVDESC TD;
  443. int tid;
  444. {
  445.     if ( ID->event_dump_hdr )
  446.         (ID->event_dump_hdr)( ID, tid );
  447.  
  448.     if ( TD->index >= 0 )
  449.     {
  450.         fprintf( ID->trace_out, "\"%s(", TD->name );
  451.  
  452.         if ( TD->entry_exit == TRC_ENTRY_TEV )
  453.             fprintf( ID->trace_out, "0." );
  454.  
  455.         else if ( TD->entry_exit == TRC_EXIT_TEV )
  456.             fprintf( ID->trace_out, "1." );
  457.  
  458.         fprintf( ID->trace_out, "%d", TD->index );
  459.  
  460.         fprintf( ID->trace_out, ")\" { " );
  461.  
  462.         /* matching } */
  463.     }
  464.  
  465.     else
  466.         fprintf( ID->trace_out, "\"%s\" { ", TD->name );
  467.         /* matching } */
  468. }
  469.  
  470.  
  471. void
  472. trc_store_data_values( ID, TD, tid, omit )
  473. TRC_ID ID;
  474. TRC_TEVDESC TD;
  475. int tid;
  476. int omit;
  477. {
  478.     TRC_DATADESC DD;
  479.  
  480.     TRC_TEVTASK TT;
  481.  
  482.     char msg[1024];
  483.  
  484.     char *str;
  485.  
  486.     int user_defined;
  487.     int newtask;
  488.     int endtask;
  489.     int maxlen;
  490.     int ignore;
  491.     int tusec;
  492.     int tsec;
  493.     int len;
  494.     int i;
  495.  
  496.     /* Set New/End Task Flags */
  497.  
  498.     TT = (TRC_TEVTASK) NULL;
  499.  
  500.     tsec = tusec = -1;
  501.  
  502.     user_defined = TRC_FALSE;
  503.     newtask = TRC_FALSE;
  504.     endtask = TRC_FALSE;
  505.  
  506.     if ( !strcmp( TD->name, "newtask" )
  507.         || !strcmp( TD->name, "spntask" ) )
  508.     {
  509.         newtask = TRC_TRUE;
  510.     }
  511.  
  512.     else if ( !strcmp( TD->name, "endtask" ) )
  513.         endtask = TRC_TRUE;
  514.  
  515.     else if ( !strcmp( TD->name, "user_defined" ) )
  516.         user_defined = TRC_TRUE;
  517.  
  518.     ignore = TRC_FALSE;
  519.  
  520.     if ( !omit )
  521.     {
  522.         /* Store Event Header */
  523.  
  524.         trc_store_event_header( ID, TD, tid );
  525.  
  526.         /* Sneak in Task ID for User Defined Events */
  527.  
  528.         if ( user_defined )
  529.             fprintf( ID->trace_out, "%d, ", tid );
  530.     }
  531.  
  532.     /* Store Data Values */
  533.  
  534.     DD = TD->ddesc;
  535.  
  536.     while ( DD != NULL )
  537.     {
  538.         /* Dump Data Value */
  539.  
  540.         if ( !omit && DD->array == TEV_DATA_ARRAY )
  541.         {
  542.             if ( DD->dt == TEV_DATA_CPLX || DD->dt == TEV_DATA_DCPLX )
  543.                 fprintf( ID->trace_out, "[%d] { ", DD->num * 2 );
  544.  
  545.             /* matching } */
  546.  
  547.             else if ( DD->dt == TEV_DATA_STRING )
  548.                 fprintf( ID->trace_out, "[%d] ", DD->num );
  549.  
  550.             else if ( DD->dt == TEV_DATA_BYTE )
  551.                 fprintf( ID->trace_out, "[%d] { ", DD->num + 1 );
  552.  
  553.             else
  554.                 fprintf( ID->trace_out, "[%d] { ", DD->num );
  555.  
  556.             /* matching } } */
  557.         }
  558.  
  559.         switch ( DD->dt )
  560.         {
  561.             case TEV_DATA_NULL: break;
  562.  
  563.             case TEV_DATA_BYTE:
  564.             {
  565.                 if ( omit )
  566.                     break;
  567.  
  568.                 if ( DD->array == TEV_DATA_ARRAY )
  569.                     fprintf( ID->trace_out, "\"" );
  570.  
  571.                 for ( i=0 ; i < DD->num ; i++ )
  572.                 {
  573.                     fprintf( ID->trace_out, "%c",
  574.                         TRC_ARR_VALUE_OF( DD->data, char, i ) );
  575.                 }
  576.  
  577.                 if ( DD->array == TEV_DATA_ARRAY )
  578.                     fprintf( ID->trace_out, "\"" );
  579.  
  580.                 break;
  581.             }
  582.  
  583.             case TEV_DATA_CPLX:
  584.             {
  585.                 if ( omit )
  586.                     break;
  587.  
  588.                 for ( i=0 ; i < DD->num ; i++ )
  589.                 {
  590.                     fprintf( ID->trace_out, "%f, %f",
  591.                         TRC_ARR_VALUE_OF( DD->data, float, 2 * i ),
  592.                         TRC_ARR_VALUE_OF( DD->data, float,
  593.                             (2 * i) + 1 ) );
  594.  
  595.                     if ( i < DD->num - 1 )
  596.                         fprintf( ID->trace_out, ", " );
  597.                 }
  598.  
  599.                 break;
  600.             }
  601.  
  602.             case TEV_DATA_DCPLX:
  603.             {
  604.                 if ( omit )
  605.                     break;
  606.  
  607.                 for ( i=0 ; i < DD->num ; i++ )
  608.                 {
  609.                     fprintf( ID->trace_out, "%lf, %lf",
  610.                         TRC_ARR_VALUE_OF( DD->data, double, 2 * i ),
  611.                         TRC_ARR_VALUE_OF( DD->data, double,
  612.                             (2 * i) + 1 ) );
  613.  
  614.                     if ( i < DD->num - 1 )
  615.                         fprintf( ID->trace_out, ", " );
  616.                 }
  617.  
  618.                 break;
  619.             }
  620.  
  621.             case TEV_DATA_DOUBLE:
  622.             {
  623.                 if ( omit )
  624.                     break;
  625.  
  626.                 for ( i=0 ; i < DD->num ; i++ )
  627.                 {
  628.                     fprintf( ID->trace_out, "%lf",
  629.                         TRC_ARR_VALUE_OF( DD->data, double, i ) );
  630.  
  631.                     if ( i < DD->num - 1 )
  632.                         fprintf( ID->trace_out, ", " );
  633.                 }
  634.  
  635.                 break;
  636.             }
  637.  
  638.             case TEV_DATA_FLOAT:
  639.             {
  640.                 if ( omit )
  641.                     break;
  642.  
  643.                 for ( i=0 ; i < DD->num ; i++ )
  644.                 {
  645.                     fprintf( ID->trace_out, "%f",
  646.                         TRC_ARR_VALUE_OF( DD->data, float, i ) );
  647.  
  648.                     if ( i < DD->num - 1 )
  649.                         fprintf( ID->trace_out, ", " );
  650.                 }
  651.  
  652.                 break;
  653.             }
  654.  
  655.             case TEV_DATA_INT:
  656.             {
  657.                 if ( !omit )
  658.                 {
  659.                     for ( i=0 ; i < DD->num ; i++ )
  660.                     {
  661.                         fprintf( ID->trace_out, "%d",
  662.                             TRC_ARR_VALUE_OF( DD->data, int, i ) );
  663.  
  664.                         if ( i < DD->num - 1 )
  665.                             fprintf( ID->trace_out, ", " );
  666.                     }
  667.                 }
  668.  
  669.                 if ( ( newtask || endtask )
  670.                     && !strcmp( DD->did->name, "TID" ) )
  671.                 {
  672.                     if ( !omit && newtask )
  673.                     {
  674.                         TT = trc_get_tevtask_tid( ID,
  675.                             TRC_VALUE_OF( DD->data, int ) );
  676.  
  677.                         if ( TT == NULL )
  678.                         {
  679.                             if ( !ignore )
  680.                             {
  681.                                 sprintf( msg,
  682.                                     "Task TID=0x%x Connected to %s",
  683.                                     TRC_VALUE_OF( DD->data, int ),
  684.                                     TRC_NAME );
  685.  
  686.                                 trc_status_msg( ID, msg );
  687.                             }
  688.  
  689.                             TT = trc_create_tevtask();
  690.  
  691.                             TT->tid = TRC_VALUE_OF( DD->data, int );
  692.  
  693.                             TT->outstatus = TRC_TASK_NOOUT;
  694.  
  695.                             TT->next = ID->tevtask_list;
  696.  
  697.                             ID->tevtask_list = TT;
  698.                         }
  699.  
  700.                         if ( !ignore )
  701.                             TT->tevstatus = TRC_TASK_ALIVE;
  702.                     
  703.                         else
  704.                             TT->tevstatus = TRC_TASK_IGNORE;
  705.                     }
  706.  
  707.                     if ( endtask )
  708.                     {
  709.                         TT = trc_get_tevtask_tid( ID,
  710.                             TRC_VALUE_OF( DD->data, int ) );
  711.  
  712.                         if ( TT != NULL )
  713.                         {
  714.                             if ( TT->tevstatus == TRC_TASK_ALIVE )
  715.                             {
  716.                                 TT->tevstatus = TRC_TASK_DEAD;
  717.  
  718.                                 trc_check_for_dead_host( ID, TT );
  719.  
  720.                                 if ( !trc_tevtasks_alive( ID ) )
  721.                                     trc_end_trace( ID );
  722.                             }
  723.  
  724.                             else
  725.                                 TT->tevstatus = TRC_TASK_DEAD;
  726.                         }
  727.  
  728.                         else if ( !omit )
  729.                         {
  730.                 printf( "\nWarning: ENDTASK Unknown Task TID=0x%x.\n\n",
  731.                             TRC_VALUE_OF( DD->data, int ) );
  732.                         }
  733.                     }
  734.                 }
  735.  
  736.                 else if ( !user_defined
  737.                     && !strcmp( DD->did->name, "TS" ) )
  738.                 {
  739.                     tsec = TRC_VALUE_OF( DD->data, int );
  740.                 }
  741.                 
  742.                 else if ( !user_defined
  743.                     && !strcmp( DD->did->name, "TU" ) )
  744.                 {
  745.                     tusec = TRC_VALUE_OF( DD->data, int );
  746.                 }
  747.  
  748.                 break;
  749.             }
  750.  
  751.             case TEV_DATA_UINT:
  752.             {
  753.                 if ( omit )
  754.                     break;
  755.  
  756.                 for ( i=0 ; i < DD->num ; i++ )
  757.                 {
  758.                     fprintf( ID->trace_out, "%u", (unsigned)
  759.                         TRC_ARR_VALUE_OF( DD->data, int, i ) );
  760.  
  761.                     if ( i < DD->num - 1 )
  762.                         fprintf( ID->trace_out, ", " );
  763.                 }
  764.  
  765.                 break;
  766.             }
  767.  
  768.             case TEV_DATA_LONG:
  769.             {
  770.                 if ( omit )
  771.                     break;
  772.  
  773.                 for ( i=0 ; i < DD->num ; i++ )
  774.                 {
  775.                     fprintf( ID->trace_out, "%ld",
  776.                         TRC_ARR_VALUE_OF( DD->data, long, i ) );
  777.  
  778.                     if ( i < DD->num - 1 )
  779.                         fprintf( ID->trace_out, ", " );
  780.                 }
  781.  
  782.                 break;
  783.             }
  784.  
  785.             case TEV_DATA_ULONG:
  786.             {
  787.                 if ( omit )
  788.                     break;
  789.  
  790.                 for ( i=0 ; i < DD->num ; i++ )
  791.                 {
  792.                     fprintf( ID->trace_out, "%ld",
  793.                         TRC_ARR_VALUE_OF( DD->data, long, i ) );
  794.  
  795.                     if ( i < DD->num - 1 )
  796.                         fprintf( ID->trace_out, ", " );
  797.                 }
  798.  
  799.                 break;
  800.             }
  801.  
  802.             case TEV_DATA_SHORT:
  803.             {
  804.                 if ( omit )
  805.                     break;
  806.  
  807.                 for ( i=0 ; i < DD->num ; i++ )
  808.                 {
  809.                     fprintf( ID->trace_out, "%d",
  810.                         TRC_ARR_VALUE_OF( DD->data, short, i ) );
  811.  
  812.                     if ( i < DD->num - 1 )
  813.                         fprintf( ID->trace_out, ", " );
  814.                 }
  815.  
  816.                 break;
  817.             }
  818.  
  819.             case TEV_DATA_USHORT:
  820.             {
  821.                 if ( omit )
  822.                     break;
  823.  
  824.                 for ( i=0 ; i < DD->num ; i++ )
  825.                 {
  826.                     fprintf( ID->trace_out, "%u",
  827.                         TRC_ARR_VALUE_OF( DD->data, short, i ) );
  828.  
  829.                     if ( i < DD->num - 1 )
  830.                         fprintf( ID->trace_out, ", " );
  831.                 }
  832.  
  833.                 break;
  834.             }
  835.  
  836.             case TEV_DATA_STRING:
  837.             {
  838.                 if ( omit )
  839.                     break;
  840.  
  841.                 if ( DD->num < 1 )
  842.                     break;
  843.  
  844.                 maxlen = 0;
  845.  
  846.                 for ( i=0 ; i < DD->num ; i++ )
  847.                 {
  848.                     len = strlen(
  849.                         TRC_ARR_VALUE_OF( DD->data, char *, i ) );
  850.  
  851.                     if ( len > maxlen )
  852.                         maxlen = len;
  853.                 }
  854.  
  855.                 if ( newtask && !strcmp( DD->did->name, "TN" ) )
  856.                 {
  857.                     if ( !(ID->group_tasks)
  858.                         && TRC_GROUPTASK( (char *) DD->data ) )
  859.                     {
  860.                         ignore = TRC_TRUE;
  861.  
  862.                         if ( TT != NULL )
  863.                         {
  864.                             sprintf( msg, "Ignoring Task \"%s\"\n",
  865.                                 (char *) DD->data );
  866.  
  867.                             trc_status_msg( ID, msg );
  868.  
  869.                             TT->tevstatus = TRC_TASK_IGNORE;
  870.                         }
  871.                     }
  872.                 }
  873.  
  874.                 fprintf( ID->trace_out, "[%d] { ", maxlen + 1 );
  875.  
  876.                 for ( i=0 ; i < DD->num ; i++ )
  877.                 {
  878.                     str = TRC_ARR_VALUE_OF( DD->data, char *, i );
  879.  
  880.                     TRC_ARR_VALUE_OF( DD->data, char *, i ) =
  881.                         (char *) NULL;
  882.  
  883.                     fprintf( ID->trace_out, "\"%s\"", str );
  884.  
  885.                     if ( i < DD->num - 1 )
  886.                         fprintf( ID->trace_out, ", " );
  887.  
  888.                     free( str );
  889.                 }
  890.  
  891.                 if ( DD->array == TEV_DATA_SCALAR )
  892.                     fprintf( ID->trace_out, " }" );
  893.  
  894.                 break;
  895.             }
  896.  
  897.             case TEV_DATA_STRUCT_START:
  898.             case TEV_DATA_STRUCT_END:
  899.             case TEV_DATA_DEFERRED:
  900.             {
  901.                 if ( !omit )
  902.                     printf( "DT %d Not Impl\n", DD->dt );
  903.  
  904.                 break;
  905.             }
  906.  
  907.             default:
  908.             {
  909.                 if ( !omit )
  910.                     printf( "DT %d Unknown\n", DD->dt );
  911.             }
  912.         }
  913.  
  914.         if ( !omit )
  915.         {
  916.             /* matching { */
  917.  
  918.             if ( DD->array == TEV_DATA_ARRAY )
  919.                 fprintf( ID->trace_out, " }" );
  920.  
  921.             if ( DD->next != NULL )
  922.                 fprintf( ID->trace_out, ", " );
  923.         }
  924.  
  925.         /* Free Data Value */
  926.  
  927.         free( DD->data );
  928.  
  929.         DD->data = (TRC_VALUE) NULL;
  930.  
  931.         DD->num = -1;
  932.  
  933.         /* Next Data Value */
  934.  
  935.         DD = DD->next;
  936.     }
  937.  
  938.     if ( !omit )
  939.     {
  940.         /* matching { */
  941.  
  942.         fprintf( ID->trace_out, " };;\n" );
  943.  
  944.         if ( tsec != -1 && tusec != -1 )
  945.             trc_update_trace_time( tsec, tusec );
  946.     }
  947. }
  948.  
  949.  
  950. int
  951. trc_store_trace_event( ID, TD, tid, omit )
  952. TRC_ID ID;
  953. TRC_TEVDESC TD;
  954. int tid;
  955. int omit;
  956. {
  957.     TRC_DATADESC DD;
  958.  
  959.     TRC_TEVTASK TT;
  960.  
  961.     char    upk_byte[TRC_MAX_UNPACK_ARR_SIZE];
  962.     float    upk_float[TRC_MAX_UNPACK_ARR_SIZE * 2];
  963.     double    upk_double[TRC_MAX_UNPACK_ARR_SIZE * 2];
  964.     int        upk_int[TRC_MAX_UNPACK_ARR_SIZE];
  965.     long    upk_long[TRC_MAX_UNPACK_ARR_SIZE];
  966.     short    upk_short[TRC_MAX_UNPACK_ARR_SIZE];
  967.     char    upk_str[TRC_MAX_UNPACK_ARR_SIZE];
  968.  
  969.     char **strarr;
  970.  
  971.     char msg[1024];
  972.  
  973.     int newtask;
  974.     int endtask;
  975.     int marker;
  976.     int maxlen;
  977.     int ignore;
  978.     int tusec;
  979.     int tsec;
  980.     int len;
  981.     int num;
  982.     int i;
  983.  
  984.     /* Dump Descriptor (if necessary) */
  985.  
  986.     if ( !omit && TD->dump )
  987.         trc_dump_tevdesc( ID, TD, tid );
  988.  
  989.     /* Set New Task Flag */
  990.  
  991.     TT = (TRC_TEVTASK) NULL;
  992.  
  993.     tsec = tusec = -1;
  994.  
  995.     newtask = TRC_FALSE;
  996.     endtask = TRC_FALSE;
  997.  
  998.     if ( !strcmp( TD->name, "newtask" )
  999.         || !strcmp( TD->name, "spntask" ) )
  1000.     {
  1001.         newtask = TRC_TRUE;
  1002.     }
  1003.  
  1004.     else if ( !strcmp( TD->name, "endtask" ) )
  1005.         endtask = TRC_TRUE;
  1006.  
  1007.     ignore = TRC_FALSE;
  1008.  
  1009.     /* Store Event Header */
  1010.  
  1011.     if ( !omit )
  1012.         trc_store_event_header( ID, TD, tid );
  1013.  
  1014.     /* Store Remainder of Event */
  1015.  
  1016.     DD = TD->ddesc;
  1017.  
  1018.     while ( DD != NULL )
  1019.     {
  1020.         if ( DD->array == TEV_DATA_ARRAY )
  1021.         {
  1022.             TRC_PVMCKERR( pvm_upkint( &num, 1, 1 ),
  1023.                 "Array Unpack", return( TRC_FALSE ) );
  1024.  
  1025.             if ( num > TRC_MAX_UNPACK_ARR_SIZE
  1026.                 && DD->dt != TEV_DATA_STRING )
  1027.             {
  1028.                 if ( !omit )
  1029.                     printf( "Error: Unpack Size %d Too Large\n", num );
  1030.  
  1031.                 return( TRC_FALSE );
  1032.             }
  1033.  
  1034.             if ( !omit )
  1035.             {
  1036.                 if ( DD->dt == TEV_DATA_CPLX
  1037.                     || DD->dt == TEV_DATA_DCPLX )
  1038.                 {
  1039.                     fprintf( ID->trace_out, "[%d] { ", num * 2 );
  1040.                     /* matching } */
  1041.                 }
  1042.  
  1043.                 else if ( DD->dt == TEV_DATA_STRING )
  1044.                     fprintf( ID->trace_out, "[%d] ", num );
  1045.  
  1046.                 else if ( DD->dt == TEV_DATA_BYTE )
  1047.                 {
  1048.                     fprintf( ID->trace_out, "[%d] { ", num + 1 );
  1049.                     /* matching } */
  1050.                 }
  1051.  
  1052.                 else
  1053.                 {
  1054.                     fprintf( ID->trace_out, "[%d] { ", num );
  1055.                     /* matching } */
  1056.                 }
  1057.             }
  1058.         }
  1059.  
  1060.         else
  1061.             num = 1;
  1062.  
  1063.         switch ( DD->dt )
  1064.         {
  1065.             case TEV_DATA_NULL: break;
  1066.  
  1067.             case TEV_DATA_BYTE:
  1068.             {
  1069.                 TRC_PVMCKERR( pvm_upkbyte( upk_byte, num, 1 ),
  1070.                     "Event BYTE Unpack", return( TRC_FALSE ) );
  1071.  
  1072.                 if ( omit )
  1073.                     break;
  1074.  
  1075.                 if ( DD->array == TEV_DATA_ARRAY )
  1076.                     fprintf( ID->trace_out, "\"" );
  1077.  
  1078.                 for ( i=0 ; i < num ; i++ )
  1079.                     fprintf( ID->trace_out, "%c", upk_byte[i] );
  1080.  
  1081.                 if ( DD->array == TEV_DATA_ARRAY )
  1082.                     fprintf( ID->trace_out, "\"" );
  1083.  
  1084.                 break;
  1085.             }
  1086.  
  1087.             case TEV_DATA_CPLX:
  1088.             {
  1089.                 TRC_PVMCKERR( pvm_upkfloat( upk_float, num * 2, 1 ),
  1090.                     "Event CPLX Unpack", return( TRC_FALSE ) );
  1091.  
  1092.                 if ( omit )
  1093.                     break;
  1094.  
  1095.                 for ( i=0 ; i < num ; i++ )
  1096.                 {
  1097.                     fprintf( ID->trace_out, "%f, %f",
  1098.                         upk_float[ 2 * i ],
  1099.                         upk_float[ (2 * i) + 1 ] );
  1100.  
  1101.                     if ( i < num - 1 )
  1102.                         fprintf( ID->trace_out, ", " );
  1103.                 }
  1104.  
  1105.                 break;
  1106.             }
  1107.  
  1108.             case TEV_DATA_DCPLX:
  1109.             {
  1110.                 TRC_PVMCKERR( pvm_upkdouble( upk_double, num * 2, 1 ),
  1111.                     "Event DCPLX Unpack", return( TRC_FALSE ) );
  1112.  
  1113.                 if ( omit )
  1114.                     break;
  1115.  
  1116.                 for ( i=0 ; i < num ; i++ )
  1117.                 {
  1118.                     fprintf( ID->trace_out, "%lf, %lf",
  1119.                         upk_double[ 2 * i ],
  1120.                         upk_double[ (2 * i) + 1 ] );
  1121.  
  1122.                     if ( i < num - 1 )
  1123.                         fprintf( ID->trace_out, ", " );
  1124.                 }
  1125.  
  1126.                 break;
  1127.             }
  1128.  
  1129.             case TEV_DATA_DOUBLE:
  1130.             {
  1131.                 TRC_PVMCKERR( pvm_upkdouble( upk_double, num, 1 ),
  1132.                     "Event DOUBLE Unpack", return( TRC_FALSE ) );
  1133.  
  1134.                 if ( omit )
  1135.                     break;
  1136.  
  1137.                 for ( i=0 ; i < num ; i++ )
  1138.                 {
  1139.                     fprintf( ID->trace_out, "%lf", upk_double[i] );
  1140.  
  1141.                     if ( i < num - 1 )
  1142.                         fprintf( ID->trace_out, ", " );
  1143.                 }
  1144.  
  1145.                 break;
  1146.             }
  1147.  
  1148.             case TEV_DATA_FLOAT:
  1149.             {
  1150.                 TRC_PVMCKERR( pvm_upkfloat( upk_float, num, 1 ),
  1151.                     "Event FLOAT Unpack", return( TRC_FALSE ) );
  1152.  
  1153.                 if ( omit )
  1154.                     break;
  1155.  
  1156.                 for ( i=0 ; i < num ; i++ )
  1157.                 {
  1158.                     fprintf( ID->trace_out, "%f", upk_float[i] );
  1159.  
  1160.                     if ( i < num - 1 )
  1161.                         fprintf( ID->trace_out, ", " );
  1162.                 }
  1163.  
  1164.                 break;
  1165.             }
  1166.  
  1167.             case TEV_DATA_INT:
  1168.             {
  1169.                 TRC_PVMCKERR( pvm_upkint( upk_int, num, 1 ),
  1170.                     "Event INT Unpack", return( TRC_FALSE ) );
  1171.  
  1172.                 if ( !omit )
  1173.                 {
  1174.                     for ( i=0 ; i < num ; i++ )
  1175.                     {
  1176.                         fprintf( ID->trace_out, "%d", upk_int[i] );
  1177.  
  1178.                         if ( i < num - 1 )
  1179.                             fprintf( ID->trace_out, ", " );
  1180.                     }
  1181.                 }
  1182.  
  1183.                 if ( ( newtask || endtask )
  1184.                     && !strcmp( DD->did->name, "TID" ) )
  1185.                 {
  1186.                     if ( !omit && newtask )
  1187.                     {
  1188.                         TT = trc_get_tevtask_tid( ID, upk_int[0] );
  1189.  
  1190.                         if ( TT == NULL )
  1191.                         {
  1192.                             if ( !ignore )
  1193.                             {
  1194.                                 sprintf( msg,
  1195.                                     "Task TID=0x%x Connected to %s",
  1196.                                     upk_int[0], TRC_NAME );
  1197.                                 
  1198.                                 trc_status_msg( ID, msg );
  1199.                             }
  1200.  
  1201.                             TT = trc_create_tevtask();
  1202.  
  1203.                             TT->tid = upk_int[0];
  1204.  
  1205.                             TT->outstatus = TRC_TASK_NOOUT;
  1206.  
  1207.                             TT->next = ID->tevtask_list;
  1208.  
  1209.                             ID->tevtask_list = TT;
  1210.                         }
  1211.  
  1212.                         if ( !ignore )
  1213.                             TT->tevstatus = TRC_TASK_ALIVE;
  1214.                     
  1215.                         else
  1216.                             TT->tevstatus = TRC_TASK_IGNORE;
  1217.                     }
  1218.  
  1219.                     if ( endtask )
  1220.                     {
  1221.                         TT = trc_get_tevtask_tid( ID, upk_int[0] );
  1222.  
  1223.                         if ( TT != NULL )
  1224.                         {
  1225.                             if ( TT->tevstatus == TRC_TASK_ALIVE )
  1226.                             {
  1227.                                 TT->tevstatus = TRC_TASK_DEAD;
  1228.  
  1229.                                 trc_check_for_dead_host( ID, TT );
  1230.  
  1231.                                 if ( !trc_tevtasks_alive( ID ) )
  1232.                                     trc_end_trace( ID );
  1233.                             }
  1234.  
  1235.                             else
  1236.                                 TT->tevstatus = TRC_TASK_DEAD;
  1237.                         }
  1238.  
  1239.                         else if ( !omit )
  1240.                         {
  1241.                 printf( "\nWarning: ENDTASK Unknown Task TID=0x%x.\n\n",
  1242.                             upk_int[0] );
  1243.                         }
  1244.                     }
  1245.                 }
  1246.  
  1247.                 else if ( !strcmp( DD->did->name, "TS" ) )
  1248.                     tsec = upk_int[0];
  1249.                 
  1250.                 else if ( !strcmp( DD->did->name, "TU" ) )
  1251.                     tusec = upk_int[0];
  1252.  
  1253.                 break;
  1254.             }
  1255.  
  1256.             case TEV_DATA_UINT:
  1257.             {
  1258.                 TRC_PVMCKERR( pvm_upkint( upk_int, num, 1 ),
  1259.                     "Event UINT Unpack", return( TRC_FALSE ) );
  1260.  
  1261.                 if ( omit )
  1262.                     break;
  1263.  
  1264.                 for ( i=0 ; i < num ; i++ )
  1265.                 {
  1266.                     fprintf( ID->trace_out, "%u",
  1267.                         (unsigned) upk_int[i] );
  1268.  
  1269.                     if ( i < num - 1 )
  1270.                         fprintf( ID->trace_out, ", " );
  1271.                 }
  1272.  
  1273.                 break;
  1274.             }
  1275.  
  1276.             case TEV_DATA_LONG:
  1277.             {
  1278.                 TRC_PVMCKERR( pvm_upklong( upk_long, num, 1 ),
  1279.                     "Event LONG Unpack", return( TRC_FALSE ) );
  1280.  
  1281.                 if ( omit )
  1282.                     break;
  1283.  
  1284.                 for ( i=0 ; i < num ; i++ )
  1285.                 {
  1286.                     fprintf( ID->trace_out, "%ld", upk_long[i] );
  1287.  
  1288.                     if ( i < num - 1 )
  1289.                         fprintf( ID->trace_out, ", " );
  1290.                 }
  1291.  
  1292.                 break;
  1293.             }
  1294.  
  1295.             case TEV_DATA_ULONG:
  1296.             {
  1297.                 TRC_PVMCKERR( pvm_upklong( upk_long, num, 1 ),
  1298.                     "Event ULONG Unpack", return( TRC_FALSE ) );
  1299.  
  1300.                 if ( omit )
  1301.                     break;
  1302.  
  1303.                 for ( i=0 ; i < num ; i++ )
  1304.                 {
  1305.                     fprintf( ID->trace_out, "%ld", upk_long[i] );
  1306.  
  1307.                     if ( i < num - 1 )
  1308.                         fprintf( ID->trace_out, ", " );
  1309.                 }
  1310.  
  1311.                 break;
  1312.             }
  1313.  
  1314.             case TEV_DATA_SHORT:
  1315.             {
  1316.                 TRC_PVMCKERR( pvm_upkshort( upk_short, num, 1 ),
  1317.                     "Event SHORT Unpack", return( TRC_FALSE ) );
  1318.  
  1319.                 if ( omit )
  1320.                     break;
  1321.  
  1322.                 for ( i=0 ; i < num ; i++ )
  1323.                 {
  1324.                     fprintf( ID->trace_out, "%d", upk_short[i] );
  1325.  
  1326.                     if ( i < num - 1 )
  1327.                         fprintf( ID->trace_out, ", " );
  1328.                 }
  1329.  
  1330.                 break;
  1331.             }
  1332.  
  1333.             case TEV_DATA_USHORT:
  1334.             {
  1335.                 TRC_PVMCKERR( pvm_upkshort( upk_short, num, 1 ),
  1336.                     "Event USHORT Unpack", return( TRC_FALSE ) );
  1337.  
  1338.                 if ( omit )
  1339.                     break;
  1340.  
  1341.                 for ( i=0 ; i < num ; i++ )
  1342.                 {
  1343.                     fprintf( ID->trace_out, "%u", upk_short[i] );
  1344.  
  1345.                     if ( i < num - 1 )
  1346.                         fprintf( ID->trace_out, ", " );
  1347.                 }
  1348.  
  1349.                 break;
  1350.             }
  1351.  
  1352.             case TEV_DATA_STRING:
  1353.             {
  1354.                 if ( num < 1 )
  1355.                     break;
  1356.  
  1357.                 strarr = (char **) malloc( (unsigned) num
  1358.                         * sizeof(char *) );
  1359.                 trc_memcheck( strarr, "String Array" );
  1360.  
  1361.                 maxlen = 0;
  1362.  
  1363.                 for ( i=0 ; i < num ; i++ )
  1364.                 {
  1365.                     TRC_PVMCKERR( pvm_upkstr( upk_str ),
  1366.                         "Event STRING Unpack", return( TRC_FALSE ) );
  1367.  
  1368.                     if ( (len = strlen( upk_str )) > maxlen )
  1369.                         maxlen = len;
  1370.  
  1371.                     strarr[i] = trc_copy_str( upk_str );
  1372.                 }
  1373.  
  1374.                 if ( !omit && newtask
  1375.                     && !strcmp( DD->did->name, "TN" ) )
  1376.                 {
  1377.                     if ( !(ID->group_tasks)
  1378.                         && TRC_GROUPTASK( upk_str ) )
  1379.                     {
  1380.                         ignore = TRC_TRUE;
  1381.  
  1382.                         if ( TT != NULL )
  1383.                         {
  1384.                             sprintf( msg,
  1385.                                 "Ignoring Task \"%s\"", upk_str );
  1386.  
  1387.                             trc_status_msg( ID, msg );
  1388.  
  1389.                             TT->tevstatus = TRC_TASK_IGNORE;
  1390.                         }
  1391.                     }
  1392.                 }
  1393.  
  1394.                 if ( !omit )
  1395.                 {
  1396.                     fprintf( ID->trace_out, "[%d] { ", maxlen + 1 );
  1397.  
  1398.                     for ( i=0 ; i < num ; i++ )
  1399.                     {
  1400.                         fprintf( ID->trace_out, "\"%s\"", strarr[i] );
  1401.  
  1402.                         if ( i < num - 1 )
  1403.                             fprintf( ID->trace_out, ", " );
  1404.  
  1405.                         free( strarr[i] );
  1406.                     }
  1407.  
  1408.                     if ( DD->array == TEV_DATA_SCALAR )
  1409.                         fprintf( ID->trace_out, " }" );
  1410.                 }
  1411.  
  1412.                 else
  1413.                 {
  1414.                     for ( i=0 ; i < num ; i++ )
  1415.                         free( strarr[i] );
  1416.                 }
  1417.  
  1418.                 free( strarr );
  1419.  
  1420.                 break;
  1421.             }
  1422.  
  1423.             case TEV_DATA_STRUCT_START:
  1424.             case TEV_DATA_STRUCT_END:
  1425.             case TEV_DATA_DEFERRED:
  1426.             {
  1427.                 if ( !omit )
  1428.                     printf( "DT Not Impl\n" );
  1429.  
  1430.                 break;
  1431.             }
  1432.  
  1433.             default:
  1434.             {
  1435.                 if ( !omit )
  1436.                     printf( "DT Unknown\n" );
  1437.             }
  1438.         }
  1439.  
  1440.         if ( !omit )
  1441.         {
  1442.             /* matching { */
  1443.  
  1444.             if ( DD->array == TEV_DATA_ARRAY )
  1445.                 fprintf( ID->trace_out, " }" );
  1446.  
  1447.             if ( DD->next != NULL )
  1448.                 fprintf( ID->trace_out, ", " );
  1449.         }
  1450.  
  1451.         DD = DD->next;
  1452.     }
  1453.  
  1454.     TRC_PVMCKERR( pvm_upkint( &marker, 1, 1 ),
  1455.         "Data ID Message", return( TRC_FALSE ) );
  1456.  
  1457.     if ( !omit )
  1458.     {
  1459.         /* matching { */
  1460.  
  1461.         if ( marker == TEV_MARK_EVENT_RECORD_END )
  1462.             fprintf( ID->trace_out, " };;\n" );
  1463.  
  1464.         else
  1465.         {
  1466.             printf( "Error: No Event End Marker\n" );
  1467.  
  1468.             return( TRC_FALSE );
  1469.         }
  1470.  
  1471.         if ( tsec != -1 && tusec != -1 )
  1472.             trc_update_trace_time( tsec, tusec );
  1473.  
  1474.         return( TRC_TRUE );
  1475.     }
  1476.  
  1477.     else
  1478.         return( TRC_FALSE );
  1479. }
  1480.  
  1481.  
  1482. trc_unpack_data_value( DD )
  1483. TRC_DATADESC DD;
  1484. {
  1485.     char upk_str[TRC_MAX_UNPACK_ARR_SIZE];
  1486.  
  1487.     int num;
  1488.     int i;
  1489.  
  1490.     if ( DD->array == TEV_DATA_ARRAY )
  1491.     {
  1492.         TRC_PVMCKERR( pvm_upkint( &num, 1, 1 ),
  1493.             "Array Unpack", return( TRC_FALSE ) );
  1494.     }
  1495.  
  1496.     else
  1497.         num = 1;
  1498.  
  1499.     DD->data = trc_make_value( DD->dt, num );
  1500.  
  1501.     DD->num = num;
  1502.  
  1503.     switch ( DD->dt )
  1504.     {
  1505.         case TEV_DATA_NULL: break;
  1506.  
  1507.         case TEV_DATA_BYTE:
  1508.         {
  1509.             TRC_PVMCKERR( pvm_upkbyte( DD->data, num, 1 ),
  1510.                 "Event BYTE Unpack", return( TRC_FALSE ) );
  1511.  
  1512.             break;
  1513.         }
  1514.  
  1515.         case TEV_DATA_CPLX:
  1516.         {
  1517.             TRC_PVMCKERR( pvm_upkfloat( DD->data, num * 2, 1 ),
  1518.                 "Event CPLX Unpack", return( TRC_FALSE ) );
  1519.  
  1520.             break;
  1521.         }
  1522.  
  1523.         case TEV_DATA_DCPLX:
  1524.         {
  1525.             TRC_PVMCKERR( pvm_upkdouble( DD->data, num * 2, 1 ),
  1526.                 "Event DCPLX Unpack", return( TRC_FALSE ) );
  1527.  
  1528.             break;
  1529.         }
  1530.  
  1531.         case TEV_DATA_DOUBLE:
  1532.         {
  1533.             TRC_PVMCKERR( pvm_upkdouble( DD->data, num, 1 ),
  1534.                 "Event DOUBLE Unpack", return( TRC_FALSE ) );
  1535.  
  1536.             break;
  1537.         }
  1538.  
  1539.         case TEV_DATA_FLOAT:
  1540.         {
  1541.             TRC_PVMCKERR( pvm_upkfloat( DD->data, num, 1 ),
  1542.                 "Event FLOAT Unpack", return( TRC_FALSE ) );
  1543.  
  1544.             break;
  1545.         }
  1546.  
  1547.         case TEV_DATA_INT:
  1548.         {
  1549.             TRC_PVMCKERR( pvm_upkint( DD->data, num, 1 ),
  1550.                 "Event INT Unpack", return( TRC_FALSE ) );
  1551.  
  1552.             break;
  1553.         }
  1554.  
  1555.         case TEV_DATA_UINT:
  1556.         {
  1557.             TRC_PVMCKERR( pvm_upkint( DD->data, num, 1 ),
  1558.                 "Event UINT Unpack", return( TRC_FALSE ) );
  1559.  
  1560.             break;
  1561.         }
  1562.  
  1563.         case TEV_DATA_LONG:
  1564.         {
  1565.             TRC_PVMCKERR( pvm_upklong( DD->data, num, 1 ),
  1566.                 "Event LONG Unpack", return( TRC_FALSE ) );
  1567.  
  1568.             break;
  1569.         }
  1570.  
  1571.         case TEV_DATA_ULONG:
  1572.         {
  1573.             TRC_PVMCKERR( pvm_upklong( DD->data, num, 1 ),
  1574.                 "Event ULONG Unpack", return( TRC_FALSE ) );
  1575.  
  1576.             break;
  1577.         }
  1578.  
  1579.         case TEV_DATA_SHORT:
  1580.         {
  1581.             TRC_PVMCKERR( pvm_upkshort( DD->data, num, 1 ),
  1582.                 "Event SHORT Unpack", return( TRC_FALSE ) );
  1583.  
  1584.             break;
  1585.         }
  1586.  
  1587.         case TEV_DATA_USHORT:
  1588.         {
  1589.             TRC_PVMCKERR( pvm_upkshort( DD->data, num, 1 ),
  1590.                 "Event USHORT Unpack", return( TRC_FALSE ) );
  1591.  
  1592.             break;
  1593.         }
  1594.  
  1595.         case TEV_DATA_STRING:
  1596.         {
  1597.             if ( num < 1 )
  1598.                 break;
  1599.  
  1600.             DD->data = (TRC_VALUE) malloc( (unsigned) num
  1601.                     * sizeof(char *) );
  1602.             trc_memcheck( DD->data, "String Array" );
  1603.  
  1604.             for ( i=0 ; i < num ; i++ )
  1605.             {
  1606.                 TRC_PVMCKERR( pvm_upkstr( upk_str ),
  1607.                     "Event STRING Unpack", return( TRC_FALSE ) );
  1608.  
  1609.                 ((char **) DD->data)[i] = trc_copy_str( upk_str );
  1610.             }
  1611.  
  1612.             break;
  1613.         }
  1614.  
  1615.         case TEV_DATA_STRUCT_START:
  1616.         case TEV_DATA_STRUCT_END:
  1617.         case TEV_DATA_DEFERRED:
  1618.             printf( "DT %d Not Impl\n", DD->dt );
  1619.             break;
  1620.  
  1621.         default:
  1622.             printf( "DT %d Unknown\n", DD->dt );
  1623.     }
  1624.  
  1625.     return( TRC_TRUE );
  1626. }
  1627.  
  1628.  
  1629. void
  1630. trc_store_tevrec( ID, TD, TR, tid )
  1631. TRC_ID ID;
  1632. TRC_TEVDESC TD;
  1633. TRC_TEVREC TR;
  1634. int tid;
  1635. {
  1636.     TRC_DATADESC DD;
  1637.  
  1638.     TRC_TEVREC trptr;
  1639.  
  1640.     char *str;
  1641.  
  1642.     int user_defined;
  1643.     int maxlen;
  1644.     int len;
  1645.     int i;
  1646.  
  1647.     /* Set New/End Task Flags */
  1648.  
  1649.     user_defined = TRC_FALSE;
  1650.  
  1651.     if ( !strcmp( TD->name, "user_defined" ) )
  1652.         user_defined = TRC_TRUE;
  1653.  
  1654.     /* Store Event Header */
  1655.  
  1656.     trc_store_event_header( ID, TD, tid );
  1657.  
  1658.     /* Sneak in Task ID for User Defined Events */
  1659.  
  1660.     if ( user_defined )
  1661.         fprintf( ID->trace_out, "%d, ", tid );
  1662.  
  1663.     /* Store Data Values */
  1664.  
  1665.     DD = TD->ddesc;
  1666.  
  1667.     trptr = TR;
  1668.  
  1669.     while ( DD != NULL )
  1670.     {
  1671.         /* Dump Data Value */
  1672.  
  1673.         if ( DD->array == TEV_DATA_ARRAY )
  1674.         {
  1675.             if ( DD->dt == TEV_DATA_STRING )
  1676.                 fprintf( ID->trace_out, "[%d] ", trptr->num );
  1677.  
  1678.             else
  1679.                 fprintf( ID->trace_out, "[%d] { ", trptr->num );
  1680.  
  1681.             /* matching } */
  1682.         }
  1683.  
  1684.         switch ( DD->dt )
  1685.         {
  1686.             case TEV_DATA_NULL: break;
  1687.  
  1688.             case TEV_DATA_BYTE:
  1689.             {
  1690.                 if ( DD->array == TEV_DATA_ARRAY )
  1691.                     fprintf( ID->trace_out, "\"" );
  1692.  
  1693.                 for ( i=0 ; i < trptr->num - 1 ; i++ )
  1694.                 {
  1695.                     fprintf( ID->trace_out, "%c",
  1696.                         TRC_ARR_VALUE_OF( trptr->value, char, i ) );
  1697.                 }
  1698.  
  1699.                 if ( DD->array == TEV_DATA_ARRAY )
  1700.                     fprintf( ID->trace_out, "\"" );
  1701.  
  1702.                 break;
  1703.             }
  1704.  
  1705.             case TEV_DATA_CPLX:
  1706.             case TEV_DATA_FLOAT:
  1707.             {
  1708.                 for ( i=0 ; i < trptr->num ; i++ )
  1709.                 {
  1710.                     fprintf( ID->trace_out, "%f",
  1711.                         TRC_ARR_VALUE_OF( trptr->value, float, i ) );
  1712.  
  1713.                     if ( i < DD->num - 1 )
  1714.                         fprintf( ID->trace_out, ", " );
  1715.                 }
  1716.  
  1717.                 break;
  1718.             }
  1719.  
  1720.             case TEV_DATA_DCPLX:
  1721.             case TEV_DATA_DOUBLE:
  1722.             {
  1723.                 for ( i=0 ; i < trptr->num ; i++ )
  1724.                 {
  1725.                     fprintf( ID->trace_out, "%lf",
  1726.                         TRC_ARR_VALUE_OF( trptr->value, double, i ) );
  1727.  
  1728.                     if ( i < trptr->num - 1 )
  1729.                         fprintf( ID->trace_out, ", " );
  1730.                 }
  1731.  
  1732.                 break;
  1733.             }
  1734.  
  1735.             case TEV_DATA_INT:
  1736.             {
  1737.                 for ( i=0 ; i < trptr->num ; i++ )
  1738.                 {
  1739.                     fprintf( ID->trace_out, "%d",
  1740.                         TRC_ARR_VALUE_OF( trptr->value, int, i ) );
  1741.  
  1742.                     if ( i < trptr->num - 1 )
  1743.                         fprintf( ID->trace_out, ", " );
  1744.                 }
  1745.  
  1746.                 break;
  1747.             }
  1748.  
  1749.             case TEV_DATA_UINT:
  1750.             {
  1751.                 for ( i=0 ; i < trptr->num ; i++ )
  1752.                 {
  1753.                     fprintf( ID->trace_out, "%u", (unsigned)
  1754.                         TRC_ARR_VALUE_OF( trptr->value, int, i ) );
  1755.  
  1756.                     if ( i < trptr->num - 1 )
  1757.                         fprintf( ID->trace_out, ", " );
  1758.                 }
  1759.  
  1760.                 break;
  1761.             }
  1762.  
  1763.             case TEV_DATA_LONG:
  1764.             {
  1765.                 for ( i=0 ; i < trptr->num ; i++ )
  1766.                 {
  1767.                     fprintf( ID->trace_out, "%ld",
  1768.                         TRC_ARR_VALUE_OF( trptr->value, long, i ) );
  1769.  
  1770.                     if ( i < trptr->num - 1 )
  1771.                         fprintf( ID->trace_out, ", " );
  1772.                 }
  1773.  
  1774.                 break;
  1775.             }
  1776.  
  1777.             case TEV_DATA_ULONG:
  1778.             {
  1779.                 for ( i=0 ; i < trptr->num ; i++ )
  1780.                 {
  1781.                     fprintf( ID->trace_out, "%ld",
  1782.                         TRC_ARR_VALUE_OF( trptr->value, long, i ) );
  1783.  
  1784.                     if ( i < trptr->num - 1 )
  1785.                         fprintf( ID->trace_out, ", " );
  1786.                 }
  1787.  
  1788.                 break;
  1789.             }
  1790.  
  1791.             case TEV_DATA_SHORT:
  1792.             {
  1793.                 for ( i=0 ; i < trptr->num ; i++ )
  1794.                 {
  1795.                     fprintf( ID->trace_out, "%d",
  1796.                         TRC_ARR_VALUE_OF( trptr->value, short, i ) );
  1797.  
  1798.                     if ( i < trptr->num - 1 )
  1799.                         fprintf( ID->trace_out, ", " );
  1800.                 }
  1801.  
  1802.                 break;
  1803.             }
  1804.  
  1805.             case TEV_DATA_USHORT:
  1806.             {
  1807.                 for ( i=0 ; i < trptr->num ; i++ )
  1808.                 {
  1809.                     fprintf( ID->trace_out, "%u",
  1810.                         TRC_ARR_VALUE_OF( trptr->value, short, i ) );
  1811.  
  1812.                     if ( i < trptr->num - 1 )
  1813.                         fprintf( ID->trace_out, ", " );
  1814.                 }
  1815.  
  1816.                 break;
  1817.             }
  1818.  
  1819.             case TEV_DATA_STRING:
  1820.             {
  1821.                 if ( trptr->num < 1 )
  1822.                     break;
  1823.  
  1824.                 maxlen = 0;
  1825.  
  1826.                 for ( i=0 ; i < trptr->num ; i++ )
  1827.                 {
  1828.                     len = strlen(
  1829.                         TRC_ARR_VALUE_OF( trptr->value, char *, i ) );
  1830.  
  1831.                     if ( len > maxlen )
  1832.                         maxlen = len;
  1833.                 }
  1834.  
  1835.                 fprintf( ID->trace_out, "[%d] { ", maxlen + 1 );
  1836.  
  1837.                 for ( i=0 ; i < trptr->num ; i++ )
  1838.                 {
  1839.                     str = TRC_ARR_VALUE_OF( trptr->value, char *, i );
  1840.  
  1841.                     fprintf( ID->trace_out, "\"%s\"", str );
  1842.  
  1843.                     if ( i < trptr->num - 1 )
  1844.                         fprintf( ID->trace_out, ", " );
  1845.  
  1846.                     free( str );
  1847.                 }
  1848.  
  1849.                 if ( DD->array == TEV_DATA_SCALAR )
  1850.                     fprintf( ID->trace_out, " }" );
  1851.  
  1852.                 break;
  1853.             }
  1854.  
  1855.             case TEV_DATA_STRUCT_START:
  1856.             case TEV_DATA_STRUCT_END:
  1857.             case TEV_DATA_DEFERRED:
  1858.             {
  1859.                 printf( "DT %d Not Impl\n", DD->dt );
  1860.  
  1861.                 break;
  1862.             }
  1863.  
  1864.             default:
  1865.             {
  1866.                 printf( "DT %d Unknown\n", DD->dt );
  1867.             }
  1868.         }
  1869.  
  1870.         /* matching { */
  1871.  
  1872.         if ( DD->array == TEV_DATA_ARRAY )
  1873.             fprintf( ID->trace_out, " }" );
  1874.  
  1875.         if ( DD->next != NULL )
  1876.             fprintf( ID->trace_out, ", " );
  1877.  
  1878.         /* Next Data Value */
  1879.  
  1880.         DD = DD->next;
  1881.  
  1882.         trptr = trptr->next;
  1883.     }
  1884.  
  1885.     /* matching { */
  1886.  
  1887.     fprintf( ID->trace_out, " };;\n" );
  1888. }
  1889.  
  1890.  
  1891. trc_store_output_event( ID, tid, str, len )
  1892. TRC_ID ID;
  1893. int tid;
  1894. char *str;
  1895. int len;
  1896. {
  1897.     TRC_TEVTASK TT;
  1898.  
  1899.     char tmp[4096];
  1900.  
  1901.     int index;
  1902.     int num;
  1903.     int i;
  1904.  
  1905.     num = 0;
  1906.  
  1907.     TT = trc_get_tevtask_tid( ID, tid );
  1908.  
  1909.     if ( TT != NULL && TT->output != NULL )
  1910.     {
  1911.         strcpy( tmp, TT->output );
  1912.  
  1913.         free( TT->output );
  1914.  
  1915.         TT->output = (char *) NULL;
  1916.  
  1917.         if ( !strcmp( str, "GOTEOF\n" ) )
  1918.         {
  1919.             trc_write_output_event( ID, tid, tmp );
  1920.  
  1921.             index = 0;
  1922.  
  1923.             num++;
  1924.         }
  1925.  
  1926.         else
  1927.             index = strlen( tmp );
  1928.     }
  1929.  
  1930.     else
  1931.         index = 0;
  1932.  
  1933.     for ( i=0 ; i < len ; i++ )
  1934.     {
  1935.         if ( str[i] != '\n' )
  1936.             tmp[index++] = str[i];
  1937.  
  1938.         else
  1939.         {
  1940.             tmp[index] = '\0';
  1941.  
  1942.             trc_write_output_event( ID, tid, tmp );
  1943.  
  1944.             index = 0;
  1945.  
  1946.             num++;
  1947.         }
  1948.     }
  1949.  
  1950.     if ( index )
  1951.     {
  1952.         tmp[index] = '\0';
  1953.  
  1954.         if ( TT != NULL )
  1955.             TT->output = trc_copy_str( tmp );
  1956.  
  1957.         else
  1958.         {
  1959.             printf( "Warning: Partial Task Output Line\n" );
  1960.  
  1961.             trc_write_output_event( ID, tid, tmp );
  1962.  
  1963.             num++;
  1964.         }
  1965.     }
  1966.  
  1967.     return( num );
  1968. }
  1969.  
  1970.  
  1971. TRC_TEVDESC_INFO_STRUCT TRC_OUTPUT_INFO[] =
  1972. {
  1973.     { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR },
  1974.     { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR },
  1975.     { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR },
  1976.     { TEV_DID_OS, TEV_DATA_STRING, TEV_DATA_SCALAR }
  1977. };
  1978.  
  1979.  
  1980. void
  1981. trc_write_output_event( ID, tid, str )
  1982. TRC_ID ID;
  1983. int tid;
  1984. char *str;
  1985. {
  1986.  
  1987. #ifdef USE_PVM_33
  1988.  
  1989.     trc_write_old_output_event( ID, tid, str );
  1990.  
  1991. #else
  1992.  
  1993.     /* Dump Task Output Into Trace File */
  1994.  
  1995.     if ( TRC_OUTPUT_TEVDESC->dump )
  1996.         trc_dump_tevdesc( ID, TRC_OUTPUT_TEVDESC, tid );
  1997.  
  1998.     trc_store_event_header( ID, TRC_OUTPUT_TEVDESC, tid );
  1999.  
  2000.     fprintf( ID->trace_out, "%d, %d, %d",
  2001.         TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, tid );
  2002.  
  2003.     trc_dump_trace_str( ID, str, TRC_TRUE );
  2004.  
  2005.     /* matching { */
  2006.  
  2007.     fprintf( ID->trace_out, " };;\n" );
  2008.  
  2009. #endif
  2010.  
  2011.     /* Dump Into Separate Output File If Requested */
  2012.  
  2013.     trc_task_output( ID, tid, str );
  2014. }
  2015.  
  2016.  
  2017. int
  2018. trc_save_host_status_events( ID )
  2019. TRC_ID ID;
  2020. {
  2021.     TRC_HOST H;
  2022.  
  2023.     int num;
  2024.  
  2025.     if ( ID->trace_out == NULL )
  2026.         return( 0 );
  2027.  
  2028.     H = TRC_HOST_LIST;
  2029.  
  2030.     num = 0;
  2031.  
  2032.     while ( H != NULL )
  2033.     {
  2034.         trc_write_host_add_event( ID, H );
  2035.  
  2036.         num++;
  2037.  
  2038.         if ( H->delta.tv_sec != 0 || H->delta.tv_usec != 0 )
  2039.         {
  2040.             trc_write_host_sync_event( ID, H );
  2041.  
  2042.             num++;
  2043.         }
  2044.  
  2045.         H = H->next;
  2046.     }
  2047.  
  2048.     if ( num )
  2049.         fflush( ID->trace_out );
  2050.  
  2051.     return( num );
  2052. }
  2053.  
  2054.  
  2055. TRC_TEVDESC_INFO_STRUCT TRC_HOST_ADD_INFO[] =
  2056. {
  2057.     { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR },
  2058.     { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR },
  2059.     { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR },
  2060.     { TEV_DID_HN, TEV_DATA_STRING, TEV_DATA_SCALAR },
  2061.     { TEV_DID_HNA, TEV_DATA_STRING, TEV_DATA_SCALAR },
  2062.     { TEV_DID_HA, TEV_DATA_STRING, TEV_DATA_SCALAR },
  2063.     { TEV_DID_HSP, TEV_DATA_INT, TEV_DATA_SCALAR }
  2064. };
  2065.  
  2066.  
  2067. void
  2068. trc_write_host_add_event( ID, H )
  2069. TRC_ID ID;
  2070. TRC_HOST H;
  2071. {
  2072.  
  2073. #ifdef USE_PVM_33
  2074.  
  2075.     trc_write_old_host_add_event( ID, H );
  2076.  
  2077. #else
  2078.  
  2079.     if ( TRC_HOST_ADD_TEVDESC->dump )
  2080.         trc_dump_tevdesc( ID, TRC_HOST_ADD_TEVDESC, H->pvmd_tid );
  2081.  
  2082.     trc_store_event_header( ID, TRC_HOST_ADD_TEVDESC, H->pvmd_tid );
  2083.  
  2084.     fprintf( ID->trace_out, "%d, %d, %d",
  2085.         TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, H->pvmd_tid );
  2086.  
  2087.     trc_dump_trace_str( ID, H->refname, TRC_TRUE );
  2088.  
  2089.     trc_dump_trace_str( ID, H->alias, TRC_TRUE );
  2090.  
  2091.     trc_dump_trace_str( ID, H->arch, TRC_TRUE );
  2092.  
  2093.     /* matching { */
  2094.  
  2095.     fprintf( ID->trace_out, ", %d };;\n", H->speed );
  2096.  
  2097. #endif
  2098.  
  2099. }
  2100.  
  2101.  
  2102. TRC_TEVDESC_INFO_STRUCT TRC_HOST_DEL_INFO[] =
  2103. {
  2104.     { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR },
  2105.     { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR },
  2106.     { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR },
  2107.     { TEV_DID_HN, TEV_DATA_STRING, TEV_DATA_SCALAR }
  2108. };
  2109.  
  2110.  
  2111. void
  2112. trc_write_host_del_event( ID, H, tid )
  2113. TRC_ID ID;
  2114. TRC_HOST H;
  2115. int tid;
  2116. {
  2117.  
  2118. #ifdef USE_PVM_33
  2119.  
  2120.     trc_write_old_host_del_event( ID, H, tid );
  2121.  
  2122. #else
  2123.  
  2124.     char tmp[1024];
  2125.  
  2126.     if ( TRC_HOST_DEL_TEVDESC->dump )
  2127.         trc_dump_tevdesc( ID, TRC_HOST_DEL_TEVDESC, tid );
  2128.  
  2129.     trc_store_event_header( ID, TRC_HOST_DEL_TEVDESC, tid );
  2130.  
  2131.     fprintf( ID->trace_out, "%d, %d, %d",
  2132.         TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, tid );
  2133.  
  2134.     if ( strcmp( H->refname, "" ) )
  2135.     {
  2136.         sscanf( H->refname, "%s", tmp );
  2137.  
  2138.         trc_dump_trace_str( ID, tmp, TRC_TRUE );
  2139.     }
  2140.  
  2141.     else
  2142.         trc_dump_trace_str( ID, H->refname, TRC_TRUE );
  2143.  
  2144.     /* matching { */
  2145.  
  2146.     fprintf( ID->trace_out, " };;\n" );
  2147.  
  2148. #endif
  2149.  
  2150. }
  2151.  
  2152.  
  2153. TRC_TEVDESC_INFO_STRUCT TRC_HOST_SYNC_INFO[] =
  2154. {
  2155.     { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR },
  2156.     { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR },
  2157.     { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR },
  2158.     { TEV_DID_HDS, TEV_DATA_INT, TEV_DATA_SCALAR },
  2159.     { TEV_DID_HDU, TEV_DATA_INT, TEV_DATA_SCALAR },
  2160. };
  2161.  
  2162.  
  2163. void
  2164. trc_write_host_sync_event( ID, H )
  2165. TRC_ID ID;
  2166. TRC_HOST H;
  2167. {
  2168.  
  2169. #ifdef USE_PVM_33
  2170.  
  2171.     trc_write_old_host_sync_event( ID, H );
  2172.  
  2173. #else
  2174.  
  2175.     if ( TRC_HOST_SYNC_TEVDESC->dump )
  2176.         trc_dump_tevdesc( ID, TRC_HOST_SYNC_TEVDESC, H->pvmd_tid );
  2177.  
  2178.     trc_store_event_header( ID, TRC_HOST_SYNC_TEVDESC, H->pvmd_tid );
  2179.  
  2180.     /* matching { */
  2181.  
  2182.     fprintf( ID->trace_out, "%d, %d, %d, %d, %d };;\n",
  2183.         TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, H->pvmd_tid,
  2184.         H->delta.tv_sec, H->delta.tv_usec );
  2185.  
  2186. #endif
  2187.  
  2188.     H->last_time.tv_sec = TRC_TRACE_TIME.tv_sec;
  2189.     H->last_time.tv_usec = TRC_TRACE_TIME.tv_usec;
  2190. }
  2191.  
  2192.  
  2193. void
  2194. trc_define_special_descriptors()
  2195. {
  2196.     unsigned info_size = sizeof( struct trc_tevdesc_info_struct );
  2197.  
  2198.     TRC_OUTPUT_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL,
  2199.         TRC_OUTPUT, TRC_IGNORE_TEV, "output", TRC_OUTPUT_INFO,
  2200.         (int) ( sizeof(TRC_OUTPUT_INFO) / info_size ) );
  2201.  
  2202.     TRC_HOST_ADD_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL,
  2203.         TRC_HOST_ADD, TRC_IGNORE_TEV, "host_add", TRC_HOST_ADD_INFO,
  2204.         (int) ( sizeof(TRC_HOST_ADD_INFO) / info_size ) );
  2205.  
  2206.     TRC_HOST_DEL_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL,
  2207.         TRC_HOST_DEL, TRC_IGNORE_TEV, "host_del", TRC_HOST_DEL_INFO,
  2208.         (int) ( sizeof(TRC_HOST_DEL_INFO) / info_size ) );
  2209.  
  2210.     TRC_HOST_SYNC_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL,
  2211.         TRC_HOST_SYNC, TRC_IGNORE_TEV, "host_sync", TRC_HOST_SYNC_INFO,
  2212.         (int) ( sizeof(TRC_HOST_SYNC_INFO) / info_size ) );
  2213. }
  2214.  
  2215.  
  2216. TRC_TEVDESC
  2217. trc_make_tevdesc( ID, eid, entry_exit, name, info, ninfo )
  2218. TRC_ID ID;
  2219. int eid;
  2220. int entry_exit;
  2221. char *name;
  2222. TRC_TEVDESC_INFO info;
  2223. int ninfo;
  2224. {
  2225.     TRC_TEVDESC_INFO TI;
  2226.  
  2227.     TRC_DATADESC DD;
  2228.  
  2229.     TRC_TEVDESC TD;
  2230.  
  2231.     int i;
  2232.  
  2233.     /* New Descriptor */
  2234.  
  2235.     TD = trc_create_tevdesc();
  2236.  
  2237.     TD->refcount = 1;
  2238.  
  2239.     TD->eid = eid;
  2240.  
  2241.     TD->entry_exit = entry_exit;
  2242.  
  2243.     TD->name = trc_copy_str( name );
  2244.  
  2245.     /* Semantic IDs / Data Types */
  2246.  
  2247.     for ( i=0 ; i < ninfo ; i++ )
  2248.     {
  2249.         TI = &(info[i]);
  2250.  
  2251.         if ( TD->ddesc == NULL )
  2252.             DD = TD->ddesc = trc_create_datadesc();
  2253.         
  2254.         else
  2255.             DD = DD->next = trc_create_datadesc();
  2256.  
  2257.         DD->did = trc_get_did( (TRC_HOST) NULL, TI->id );
  2258.  
  2259.         DD->dt = TI->dt;
  2260.  
  2261.         DD->array = TI->array;
  2262.     }
  2263.  
  2264.     trc_add_tevdesc( ID, &TD, TRC_TID, TRC_FALSE );
  2265.  
  2266.     return( TD );
  2267. }
  2268.  
  2269.  
  2270. /* Handle Task Output */
  2271.  
  2272. void
  2273. trc_task_output( ID, tid, str )
  2274. TRC_ID ID;
  2275. int tid;
  2276. char *str;
  2277. {
  2278.     char tmp[4096];
  2279.  
  2280.     if ( ID->output_fp == NULL )
  2281.         return;
  2282.  
  2283.     if ( !strcmp( str, "GOTEOF" ) )
  2284.     {
  2285.         if ( ID->output_dump_hdr )
  2286.         {
  2287.             (ID->output_dump_hdr)( ID, tid );
  2288.  
  2289.             fprintf( ID->output_fp, "EOF\n" );
  2290.         }
  2291.  
  2292.         else
  2293.             fprintf( ID->output_fp, "[0x%x] EOF\n", tid );
  2294.  
  2295.         fflush( ID->output_fp );
  2296.     }
  2297.  
  2298.     else if ( strcmp( str, "CREATION" ) && strcmp( str, "GOTSPAWN" ) )
  2299.     {
  2300.         if ( ID->output_dump_hdr )
  2301.         {
  2302.             (ID->output_dump_hdr)( ID, tid );
  2303.  
  2304.             fprintf( ID->output_fp, "%s\n", str );
  2305.         }
  2306.  
  2307.         else
  2308.             fprintf( ID->output_fp, "[0x%x] %s\n", tid, str );
  2309.  
  2310.         fflush( ID->output_fp );
  2311.     }
  2312. }
  2313.  
  2314.  
  2315. /* Time Routines */
  2316.  
  2317. void
  2318. trc_update_trace_time( sec, usec )
  2319. int sec;
  2320. int usec;
  2321. {
  2322.     struct timeval tm;
  2323.  
  2324.     if ( sec == -1 )
  2325.     {
  2326.         gettimeofday( &tm, (struct timezone *) NULL );
  2327.  
  2328.         sec = tm.tv_sec;
  2329.         usec = tm.tv_usec;
  2330.     }
  2331.  
  2332.     if ( sec > TRC_TRACE_TIME.tv_sec ||
  2333.         ( sec == TRC_TRACE_TIME.tv_sec
  2334.             && usec > TRC_TRACE_TIME.tv_usec ) )
  2335.     {
  2336.         TRC_TRACE_TIME.tv_sec = sec;
  2337.         TRC_TRACE_TIME.tv_usec = usec;
  2338.     }
  2339. }
  2340.  
  2341.  
  2342. /* Trace Utility Routines */
  2343.  
  2344. void
  2345. trc_dump_trace_header( ID )
  2346. TRC_ID ID;
  2347. {
  2348.     char *ds;
  2349.  
  2350.     if ( ID->trace_out == NULL )
  2351.         return;
  2352.  
  2353.     if ( ID->event_dump_hdr )
  2354.         (ID->event_dump_hdr)( ID, TRC_TID );
  2355.  
  2356.     fprintf( ID->trace_out, "/*\n" );
  2357.  
  2358.     if ( ID->event_dump_hdr )
  2359.         (ID->event_dump_hdr)( ID, TRC_TID );
  2360.  
  2361.     ds = trc_date_str();
  2362.  
  2363.     fprintf( ID->trace_out, " * \"Creation Date\" \"%s\"\n", ds );
  2364.  
  2365.     free( ds );
  2366.  
  2367.     if ( ID->event_dump_hdr )
  2368.         (ID->event_dump_hdr)( ID, TRC_TID );
  2369.  
  2370.     fprintf( ID->trace_out, " * \"Machine\" \"%s %s (PVM %s)\"\n",
  2371.         TRC_NAME, TRC_VERSION, pvm_version() );
  2372.  
  2373.     if ( ID->event_dump_hdr )
  2374.         (ID->event_dump_hdr)( ID, TRC_TID );
  2375.  
  2376.     fprintf( ID->trace_out, " */ ;;\n" );
  2377.  
  2378.     if ( ID->event_dump_hdr )
  2379.         (ID->event_dump_hdr)( ID, TRC_TID );
  2380.  
  2381.     fprintf( ID->trace_out, "\n" );
  2382. }
  2383.  
  2384.  
  2385. void
  2386. trc_dump_trace_str( ID, str, comma_flag )
  2387. TRC_ID ID;
  2388. char *str;
  2389. int comma_flag;
  2390. {
  2391.     if ( comma_flag )
  2392.     {
  2393.         fprintf( ID->trace_out, ", [%d] { \"%s\" }",
  2394.             strlen( str ) + 1, str );
  2395.     }
  2396.  
  2397.     else
  2398.     {
  2399.         fprintf( ID->trace_out, "[%d] { \"%s\" }",
  2400.             strlen( str ) + 1, str );
  2401.     }
  2402. }
  2403.  
  2404.  
  2405. /* Trace Processing Routines */
  2406.  
  2407. int
  2408. trc_read_trace_event( ID, eof )
  2409. TRC_ID ID;
  2410. int *eof;
  2411. {
  2412.     TRC_TEVDESC TD;
  2413.  
  2414.     char tmp[4096];
  2415.     char c;
  2416.  
  2417.     int entry_exit;
  2418.     int dummy;
  2419.     int index;
  2420.     int code;
  2421.     int flag;
  2422.     int eid;
  2423.     int ee;
  2424.     int i;
  2425.  
  2426.     *eof = TRC_FALSE;
  2427.  
  2428.     if ( ID->trace_in == NULL )
  2429.         return( TRC_FALSE );
  2430.  
  2431.     while ( TRC_TRUE )
  2432.     {
  2433.         c = getc( ID->trace_in );
  2434.  
  2435.         if ( c != (char) EOF )
  2436.         {
  2437.             switch ( c )
  2438.             {
  2439.                 /* Record Descriptor Packet */
  2440.  
  2441.                 case '#':
  2442.                 {
  2443.                     /* Get event ID */
  2444.  
  2445.                     flag = fscanf( ID->trace_in, "%d", &code );
  2446.  
  2447.                     if ( flag != 1 )
  2448.                     {
  2449.                         printf( "Error Reading Event ID\n" );
  2450.  
  2451.                         return( TRC_FALSE );
  2452.                     }
  2453.  
  2454.                     /* Get event name */
  2455.  
  2456.                     if ( !trc_find_event_str( ID, "\"" ) )
  2457.                         return( TRC_FALSE );
  2458.  
  2459.                     i = 0;
  2460.  
  2461.                     while ( (c = getc( ID->trace_in )) != (char) EOF
  2462.                         && c != '"' && c != '(' )
  2463.                     {
  2464.                         tmp[i++] = c;
  2465.                     }
  2466.  
  2467.                     TRC_CKEOF( c, "EOF Reading Event Descriptor Name\n",
  2468.                         return( TRC_FALSE ) );
  2469.  
  2470.                     tmp[i] = '\0';
  2471.  
  2472.                     /* PVM 3.4 Trace */
  2473.  
  2474.                     if ( c == '(' )
  2475.                     {
  2476.                         /* Decode event ID */
  2477.  
  2478.                         index = ( code / 1000 ) - 1;
  2479.  
  2480.                         eid = ( code - ((index + 1) * 1000) ) / 2;
  2481.  
  2482.                         ee = code - ((index + 1) * 1000) - (2 * eid);
  2483.  
  2484.                         /* Read in entry/exit or index value */
  2485.  
  2486.                         flag = fscanf( ID->trace_in, "%d", &dummy );
  2487.  
  2488.                         if ( flag != 1 )
  2489.                         {
  2490.                             printf( "Error Reading Event Index\n" );
  2491.  
  2492.                             return( TRC_FALSE );
  2493.                         }
  2494.  
  2495.                         /* Read in next char for parsing context */
  2496.  
  2497.                         c = getc( ID->trace_in );
  2498.  
  2499.                         TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2500.                             return( TRC_FALSE ) );
  2501.  
  2502.                         if ( c == '.' )
  2503.                         {
  2504.                             if ( ee != dummy )
  2505.                             {
  2506.                                 printf( "Warning:  " );
  2507.                                 printf( "Entry/Exit Mismatch  " );
  2508.                                 printf( "%d != %d\n", ee, dummy );
  2509.                             }
  2510.  
  2511.                             entry_exit = TRC_IGNORE_TEV;
  2512.  
  2513.                             if ( dummy == 0 )
  2514.                                 entry_exit = TRC_ENTRY_TEV;
  2515.  
  2516.                             else if ( dummy == 1 )
  2517.                                 entry_exit = TRC_EXIT_TEV;
  2518.  
  2519.                             flag = fscanf( ID->trace_in, "%d", &dummy );
  2520.  
  2521.                             if ( flag != 1 )
  2522.                             {
  2523.                                 printf( "Error Reading Event Index\n" );
  2524.  
  2525.                                 return( TRC_FALSE );
  2526.                             }
  2527.  
  2528.                             if ( index != dummy )
  2529.                             {
  2530.                                 printf( "Warning:  " );
  2531.                                 printf( "Descriptor Index Mismatch  " );
  2532.                                 printf( "%d != %d\n", index, dummy );
  2533.  
  2534.                                 index = dummy;
  2535.                             }
  2536.  
  2537.                             if ( !trc_find_event_str( ID, ")" ) )
  2538.                                 return( TRC_FALSE );
  2539.                         }
  2540.  
  2541.                         else
  2542.                         {
  2543.                             entry_exit = TRC_IGNORE_TEV;
  2544.  
  2545.                             if ( ee == 1 )
  2546.                             {
  2547.                                 printf( "Warning:  " );
  2548.                                 printf( "Entry/Exit Mismatch  " );
  2549.                                 printf( "%d != %d\n", ee, entry_exit );
  2550.                             }
  2551.  
  2552.                             if ( index != dummy )
  2553.                             {
  2554.                                 printf( "Warning:  " );
  2555.                                 printf( "Descriptor Index Mismatch  " );
  2556.                                 printf( "%d != %d\n", index, dummy );
  2557.  
  2558.                                 index = dummy;
  2559.                             }
  2560.                         }
  2561.  
  2562.                         if ( !trc_find_event_str( ID, "\"" ) )
  2563.                             return( TRC_FALSE );
  2564.  
  2565.                         if ( !(TD = trc_read_descriptor(
  2566.                             ID, eid, tmp, entry_exit, index )) )
  2567.                         {
  2568.                             return( TRC_FALSE );
  2569.                         }
  2570.  
  2571.                         if ( ID->handle_descriptor )
  2572.                             (ID->handle_descriptor)( ID, TD );
  2573.                     }
  2574.  
  2575.                     /* PVM 3.3 Trace - Ignore Descriptor */
  2576.  
  2577.                     else
  2578.                     {
  2579.                         eid = code;
  2580.  
  2581.                         if ( tmp[ i - 1 ] == '0' )
  2582.                             entry_exit = TRC_ENTRY_TEV;
  2583.  
  2584.                         else if ( tmp[ i - 1 ] == '1' )
  2585.                             entry_exit = TRC_EXIT_TEV;
  2586.  
  2587.                         else
  2588.                             entry_exit = TRC_IGNORE_TEV;
  2589.  
  2590.                         if ( !(TD = trc_read_descriptor(
  2591.                             ID, eid, tmp, entry_exit, -1 )) )
  2592.                         {
  2593.                             return( TRC_FALSE );
  2594.                         }
  2595.  
  2596.                         if ( ID->handle_old_descriptor )
  2597.                             (ID->handle_old_descriptor)( ID, TD );
  2598.                     }
  2599.  
  2600.                     break;
  2601.                 }
  2602.  
  2603.                 /* Record Data Packet */
  2604.  
  2605.                 case '"':
  2606.                 {
  2607.                     i = 0;
  2608.  
  2609.                     while ( (c = getc( ID->trace_in )) != (char) EOF
  2610.                         && c != '"' && c != '(' )
  2611.                     {
  2612.                         tmp[i++] = c;
  2613.                     }
  2614.  
  2615.                     TRC_CKEOF( c, "EOF Reading Event Record Name\n",
  2616.                         return( TRC_FALSE ) );
  2617.  
  2618.                     tmp[i] = '\0';
  2619.  
  2620.                     /* PVM 3.4 Trace */
  2621.  
  2622.                     if ( c == '(' )
  2623.                     {
  2624.                         /* Read in entry/exit or index value */
  2625.  
  2626.                         flag = fscanf( ID->trace_in, "%d", &dummy );
  2627.  
  2628.                         if ( flag != 1 )
  2629.                         {
  2630.                             printf( "Error Reading Event Index\n" );
  2631.  
  2632.                             return( TRC_FALSE );
  2633.                         }
  2634.  
  2635.                         /* Read in next char for parsing context */
  2636.  
  2637.                         c = getc( ID->trace_in );
  2638.  
  2639.                         TRC_CKEOF( c, "EOF Reading Event Record\n",
  2640.                             return( TRC_FALSE ) );
  2641.  
  2642.                         if ( c == '.' )
  2643.                         {
  2644.                             entry_exit = TRC_IGNORE_TEV;
  2645.  
  2646.                             if ( dummy == 0 )
  2647.                                 entry_exit = TRC_ENTRY_TEV;
  2648.                             
  2649.                             else if ( dummy == 1 )
  2650.                                 entry_exit = TRC_EXIT_TEV;
  2651.                             
  2652.                             flag = fscanf( ID->trace_in, "%d", &index );
  2653.  
  2654.                             if ( flag != 1 )
  2655.                             {
  2656.                                 printf( "Error Reading Event Index\n" );
  2657.  
  2658.                                 return( TRC_FALSE );
  2659.                             }
  2660.  
  2661.                             if ( !trc_find_event_str( ID, ")" ) )
  2662.                                 return( TRC_FALSE );
  2663.                         }
  2664.  
  2665.                         else
  2666.                         {
  2667.                             entry_exit = TRC_IGNORE_TEV;
  2668.  
  2669.                             index = dummy;
  2670.                         }
  2671.  
  2672.                         if ( !trc_find_event_str( ID, "\"" ) )
  2673.                             return( TRC_FALSE );
  2674.  
  2675.                         return( trc_process_trace_event(
  2676.                             ID, tmp, entry_exit, index ) );
  2677.                     }
  2678.  
  2679.                     /* PVM 3.3 Trace */
  2680.  
  2681.                     else
  2682.                     {
  2683.                         return(
  2684.                             trc_process_old_trace_event( ID, tmp ) );
  2685.                     }
  2686.  
  2687.                     /* break; unreachable */
  2688.                 }
  2689.  
  2690.                 /* Command Packet */
  2691.  
  2692.                 case '%':
  2693.                 {
  2694.                     tmp[0] = '%';
  2695.  
  2696.                     if ( !trc_find_event_end_ret( ID, tmp + 1, 4095 ) )
  2697.                         return( TRC_FALSE );
  2698.  
  2699.                     if ( ID->handle_command )
  2700.                         (ID->handle_command)( ID, tmp );
  2701.  
  2702.                     break;
  2703.                 }
  2704.  
  2705.                 /* Stream Attribute Packet */
  2706.  
  2707.                 case '/':
  2708.                 {
  2709.                     c = getc( ID->trace_in );
  2710.  
  2711.                     TRC_CKEOF( c, "EOF Reading Trace Comment\n",
  2712.                         return( TRC_FALSE ) );
  2713.  
  2714.                     if ( c != '*' )
  2715.                     {
  2716.                         printf( "\nError Reading Trace File\n" );
  2717.                         printf( "\t- '*' expected (/* */)\n\n" );
  2718.                     }
  2719.  
  2720.                     strcpy( tmp, "/*" );
  2721.  
  2722.                     if ( !trc_find_event_end_ret( ID, tmp + 2, 4094 ) )
  2723.                         return( TRC_FALSE );
  2724.  
  2725.                     if ( ID->handle_comment )
  2726.                         (ID->handle_comment)( ID, tmp );
  2727.  
  2728.                     break;
  2729.                 }
  2730.  
  2731.                 /* White Space */
  2732.  
  2733.                 case ' ':
  2734.                 case '\t':
  2735.                 case '\n':
  2736.                 {
  2737.                     break;
  2738.                 }
  2739.             }
  2740.         }
  2741.  
  2742.         else
  2743.         {
  2744.             *eof = TRC_TRUE;
  2745.  
  2746.             return( TRC_FALSE );
  2747.         }
  2748.     }
  2749. }
  2750.  
  2751.  
  2752. TRC_TEVDESC
  2753. trc_read_descriptor( ID, eid, name, entry_exit, index )
  2754. TRC_ID ID;
  2755. int eid;
  2756. char *name;
  2757. int entry_exit;
  2758. int index;
  2759. {
  2760.     TRC_DATADESC DD;
  2761.  
  2762.     TRC_TEVDESC TD;
  2763.     TRC_TEVDESC tdptr;
  2764.  
  2765.     char diddesc[1024];
  2766.     char dtstr[255];
  2767.     char did[8];
  2768.  
  2769.     char last;
  2770.     char c;
  2771.  
  2772.     long tmp;
  2773.  
  2774.     int done;
  2775.     int i;
  2776.  
  2777.     /* Find first bracket */
  2778.  
  2779.     if ( !trc_find_event_str( ID, "{" ) )
  2780.         return( (TRC_TEVDESC) NULL );
  2781.  
  2782.     /* matching } */
  2783.  
  2784.     /* Create Descriptor Structure */
  2785.  
  2786.     TD = trc_create_tevdesc();
  2787.  
  2788.     TD->refcount = 1;
  2789.  
  2790.     TD->name = trc_copy_str( name );
  2791.  
  2792.     TD->eid = eid;
  2793.  
  2794.     TD->entry_exit = entry_exit;
  2795.  
  2796.     TD->index = index;
  2797.  
  2798.     /* Read in Data Descriptor Statements */
  2799.  
  2800.     done = 0;
  2801.  
  2802.     do
  2803.     {
  2804.         /* matching { */
  2805.  
  2806.         while ( (c = getc( ID->trace_in )) != (char) EOF
  2807.             && c != '/' && c != '}' );
  2808.  
  2809.         TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2810.             return( (TRC_TEVDESC) NULL ) );
  2811.  
  2812.         /* Another Descriptor Statement */
  2813.  
  2814.         if ( c == '/' )
  2815.         {
  2816.             if ( TD->ddesc == NULL )
  2817.                 DD = TD->ddesc = trc_create_datadesc();
  2818.  
  2819.             else
  2820.                 DD = DD->next = trc_create_datadesc();
  2821.  
  2822.             /* Get Second '/' */
  2823.  
  2824.             c = getc( ID->trace_in );
  2825.  
  2826.             TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2827.                 return( (TRC_TEVDESC) NULL ) );
  2828.  
  2829.             if ( c != '/' )
  2830.             {
  2831.                 printf( "Error Parsing Event Descriptor\n" );
  2832.  
  2833.                 return( (TRC_TEVDESC) NULL );
  2834.             }
  2835.  
  2836.             /* Read in TRC_DID Name */
  2837.  
  2838.             if ( !trc_find_event_str( ID, "\"" ) )
  2839.                 return( (TRC_TEVDESC) NULL );
  2840.  
  2841.             i = 0;
  2842.  
  2843.             while ( (c = getc( ID->trace_in )) != (char) EOF
  2844.                 && c != '"' && i < 8 )
  2845.             {
  2846.                 did[i++] = c;
  2847.             }
  2848.  
  2849.             TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2850.                 return( (TRC_TEVDESC) NULL ) );
  2851.  
  2852.             if ( c != '"' )
  2853.             {
  2854.                 printf( "Error Parsing Event Descriptor\n" );
  2855.  
  2856.                 return( (TRC_TEVDESC) NULL );
  2857.             }
  2858.  
  2859.             did[i] = '\0';
  2860.  
  2861.             /* Read in TRC_DID Description */
  2862.  
  2863.             if ( !trc_find_event_str( ID, "\"" ) )
  2864.                 return( (TRC_TEVDESC) NULL );
  2865.  
  2866.             i = 0;
  2867.  
  2868.             while ( (c = getc( ID->trace_in )) != (char) EOF
  2869.                 && c != '"' && i < 1024 )
  2870.             {
  2871.                 diddesc[i++] = c;
  2872.             }
  2873.  
  2874.             TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2875.                 return( (TRC_TEVDESC) NULL ) );
  2876.  
  2877.             if ( c != '"' )
  2878.             {
  2879.                 printf( "Error Parsing Event Descriptor\n" );
  2880.  
  2881.                 return( (TRC_TEVDESC) NULL );
  2882.             }
  2883.  
  2884.             diddesc[i] = '\0';
  2885.  
  2886.             /* Get Descriptor TRC_DID struct */
  2887.  
  2888.             DD->did = (TRC_DID) trc_lookup_trie( TRC_DID_TRIE,
  2889.                 (void *) did );
  2890.  
  2891.             if ( DD->did == NULL )
  2892.             {
  2893.                 DD->did = trc_create_did();
  2894.  
  2895.                 DD->did->name = trc_copy_str( did );
  2896.  
  2897.                 DD->did->desc = trc_copy_str( diddesc );
  2898.             }
  2899.  
  2900.             /* Get Data Type */
  2901.  
  2902.             while ( (c = getc( ID->trace_in )) != (char) EOF
  2903.                 && ( c == ' ' || c == '\t' || c == '\n' ) );
  2904.  
  2905.             TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2906.                 return( (TRC_TEVDESC) NULL ) );
  2907.  
  2908.             dtstr[0] = c;
  2909.  
  2910.             i = 1;
  2911.  
  2912.             while ( (c = getc( ID->trace_in )) != (char) EOF
  2913.                 && c != ' ' && c != '\t' && c != '\n' && c != '"' )
  2914.             {
  2915.                 dtstr[i++] = c;
  2916.             }
  2917.  
  2918.             TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2919.                 return( (TRC_TEVDESC) NULL ) );
  2920.  
  2921.             dtstr[i] = '\0';
  2922.  
  2923.             DD->dt = trc_get_dt_str( dtstr );
  2924.  
  2925.             if ( DD->dt < 0 )
  2926.             {
  2927.                 printf( "Error: Unknown Data Type \"%s\".\n", dtstr );
  2928.  
  2929.                 return( (TRC_TEVDESC) NULL );
  2930.             }
  2931.  
  2932.             /* Skip over var name */
  2933.  
  2934.             if ( c != '"' )
  2935.             {
  2936.                 if ( !trc_find_event_str( ID, "\"" ) )
  2937.                     return( (TRC_TEVDESC) NULL );
  2938.             }
  2939.  
  2940.             if ( !trc_find_event_str( ID, "\"" ) )
  2941.                 return( (TRC_TEVDESC) NULL );
  2942.  
  2943.             /* Check for Data Array */
  2944.  
  2945.             c = getc( ID->trace_in );
  2946.  
  2947.             TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2948.                 return( (TRC_TEVDESC) NULL ) );
  2949.  
  2950.             if ( c == '[' )
  2951.             {
  2952.                 if ( DD->dt == TEV_DATA_BYTE
  2953.                     || DD->dt == TEV_DATA_STRING )
  2954.                 {
  2955.                     /* Get closing ']' */
  2956.  
  2957.                     c = getc( ID->trace_in );
  2958.  
  2959.                     TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2960.                         return( (TRC_TEVDESC) NULL ) );
  2961.  
  2962.                     if ( c != ']' )
  2963.                     {
  2964.                         printf( "Error Parsing Event Descriptor\n" );
  2965.  
  2966.                         return( (TRC_TEVDESC) NULL );
  2967.                     }
  2968.  
  2969.                     /* Check for another [] */
  2970.  
  2971.                     c = getc( ID->trace_in );
  2972.  
  2973.                     TRC_CKEOF( c, "EOF Reading Event Descriptor\n",
  2974.                         return( (TRC_TEVDESC) NULL ) );
  2975.  
  2976.                     /* [][] -> STRING[] */
  2977.                     if ( c == '[' )
  2978.                     {
  2979.                         if ( DD->dt == TEV_DATA_BYTE )
  2980.                             DD->dt = TEV_DATA_STRING;
  2981.  
  2982.                         DD->array = TEV_DATA_ARRAY;
  2983.                     }
  2984.  
  2985.                     /* [] -> BYTE[] */
  2986.                     else
  2987.                     {
  2988.                         if ( DD->dt == TEV_DATA_STRING )
  2989.                             DD->dt = TEV_DATA_BYTE;
  2990.  
  2991.                         DD->array = TEV_DATA_ARRAY;
  2992.                     }
  2993.                 }
  2994.  
  2995.                 else
  2996.                     DD->array = TEV_DATA_ARRAY;
  2997.             }
  2998.  
  2999.             else
  3000.                 DD->array = TEV_DATA_SCALAR;
  3001.         }
  3002.  
  3003.         /* End of Descriptor */
  3004.  
  3005.         else
  3006.         {
  3007.             if ( !trc_find_event_end( ID ) )
  3008.                 return( (TRC_TEVDESC) NULL );
  3009.  
  3010.             done++;
  3011.         }
  3012.     }
  3013.     while ( !done );
  3014.  
  3015.     tdptr = (TRC_TEVDESC) trc_lookup_trie( TRC_EVENT_TRIE, name );
  3016.  
  3017.     if ( tdptr == NULL )
  3018.         trc_add_to_trie( TRC_EVENT_TRIE, name, (void *) TD );
  3019.  
  3020.     else
  3021.     {
  3022.         while ( tdptr->next != NULL )
  3023.         {
  3024.             if ( trc_cmp_tevdesc( TD, tdptr ) )
  3025.             {
  3026.                 trc_free_tevdesc( &TD );
  3027.  
  3028.                 return( tdptr );
  3029.             }
  3030.  
  3031.             tdptr = tdptr->next;
  3032.         }
  3033.  
  3034.         if ( trc_cmp_tevdesc( TD, tdptr ) )
  3035.         {
  3036.             trc_free_tevdesc( &TD );
  3037.  
  3038.             return( tdptr );
  3039.         }
  3040.  
  3041.         else
  3042.             tdptr->next = TD;
  3043.     }
  3044.  
  3045.     /* Set Handle ID */
  3046.  
  3047.     tmp = (long) trc_lookup_trie( TRC_HANDLE_TRIE, TD->name );
  3048.  
  3049.     TD->hid = (int) tmp;
  3050.  
  3051.     return( TD );
  3052. }
  3053.  
  3054.  
  3055. int
  3056. trc_process_trace_event( ID, name, entry_exit, index )
  3057. TRC_ID ID;
  3058. char *name;
  3059. int entry_exit;
  3060. int index;
  3061. {
  3062.     TRC_DATADESC DD;
  3063.  
  3064.     TRC_TEVDESC TD;
  3065.  
  3066.     TRC_TEVREC TR;
  3067.     TRC_TEVREC trptr;
  3068.  
  3069.     char    read_str[TRC_MAX_UNPACK_ARR_SIZE];
  3070.     double    read_double;
  3071.     float    read_float;
  3072.     short    read_short;
  3073.     long    read_long;
  3074.     int        read_int;
  3075.  
  3076.     char c;
  3077.  
  3078.     int i, j;
  3079.     int flag;
  3080.     int num;
  3081.  
  3082.     if ( !(ID->handle_event) )
  3083.     {
  3084.         trc_find_event_end( ID );
  3085.  
  3086.         return( TRC_TRUE );
  3087.     }
  3088.  
  3089.     TD = (TRC_TEVDESC) trc_lookup_trie( TRC_EVENT_TRIE, name );
  3090.  
  3091.     while ( TD != NULL &&
  3092.         ( TD->entry_exit != entry_exit || TD->index != index ) )
  3093.     {
  3094.         TD = TD->next;
  3095.     }
  3096.  
  3097.     if ( TD == NULL )
  3098.     {
  3099.         printf( "Error: Event \"%s\" Descriptor Not Found\n", name );
  3100.  
  3101.         trc_find_event_end( ID );
  3102.  
  3103.         return( TRC_FALSE );
  3104.     }
  3105.  
  3106.     if ( !trc_find_event_str( ID, "{" ) )
  3107.         return( TRC_FALSE );
  3108.     
  3109.     /* matching } */
  3110.  
  3111.     DD = TD->ddesc;
  3112.  
  3113.     TR = (TRC_TEVREC) NULL;
  3114.  
  3115.     while ( DD != NULL )
  3116.     {
  3117.         if ( TR == NULL )
  3118.             trptr = TR = trc_create_tevrec();
  3119.         
  3120.         else
  3121.             trptr = trptr->next = trc_create_tevrec();
  3122.  
  3123.         trptr->ddesc = DD;
  3124.  
  3125.         if ( DD->array == TEV_DATA_ARRAY )
  3126.         {
  3127.             if ( !trc_find_event_str( ID, "[" ) )
  3128.                 return( TRC_FALSE );
  3129.  
  3130.             flag = fscanf( ID->trace_in, "%d", &num );
  3131.  
  3132.             if ( flag != 1 )
  3133.             {
  3134.                 printf( "Error Parsing Event Record\n" );
  3135.  
  3136.                 trc_find_event_end( ID );
  3137.  
  3138.                 return( TRC_FALSE );
  3139.             }
  3140.  
  3141.             if ( !trc_find_event_str( ID, "{" ) )
  3142.                 return( TRC_FALSE );
  3143.  
  3144.             /* matching } */
  3145.         }
  3146.  
  3147.         else
  3148.             num = 1;
  3149.  
  3150.         trptr->value = trc_make_value( DD->dt, num );
  3151.  
  3152.         if ( trptr->value == NULL )
  3153.         {
  3154.             printf( "Error Allocating Value dt=%d num=%d\n",
  3155.                 DD->dt, num );
  3156.  
  3157.             return( TRC_FALSE );
  3158.         }
  3159.  
  3160.         trptr->num = num;
  3161.  
  3162.         switch ( DD->dt )
  3163.         {
  3164.             case TEV_DATA_NULL: break;
  3165.  
  3166.             case TEV_DATA_BYTE:
  3167.             {
  3168.                 if ( DD->array == TEV_DATA_ARRAY )
  3169.                 {
  3170.                     if ( !trc_find_event_str( ID, "\"" ) )
  3171.                         return( TRC_FALSE );
  3172.  
  3173.                     i = 0;
  3174.  
  3175.                     while ( i < num
  3176.                         && (c = getc( ID->trace_in )) != (char) EOF
  3177.                         && c != '"' )
  3178.                     {
  3179.                         TRC_ARR_VALUE_OF( trptr->value, char, i++ ) = c;
  3180.                     }
  3181.  
  3182.                     TRC_CKEOF( c, "EOF Parsing Event Record\n",
  3183.                         return( TRC_FALSE ) );
  3184.  
  3185.                     if ( i == num )
  3186.                     {
  3187.                         printf( "Error: Character Overflow\n" );
  3188.  
  3189.                         return( TRC_FALSE );
  3190.                     }
  3191.  
  3192.                     TRC_ARR_VALUE_OF( trptr->value, char, i ) = '\0';
  3193.                 }
  3194.  
  3195.                 else
  3196.                 {
  3197.                     while ( (c = getc( ID->trace_in )) != (char) EOF
  3198.                         && ( c == ' ' || c == '\t' || c == '\n' ) );
  3199.  
  3200.                     TRC_CKEOF( c, "EOF Parsing Event Record\n",
  3201.                         return( TRC_FALSE ) );
  3202.  
  3203.                     TRC_VALUE_OF( trptr->value, char ) = c;
  3204.                 }
  3205.  
  3206.                 break;
  3207.             }
  3208.  
  3209.             case TEV_DATA_CPLX:
  3210.             case TEV_DATA_FLOAT:
  3211.             {
  3212.                 for ( i=0 ; i < num ; i++ )
  3213.                 {
  3214.                     flag = fscanf( ID->trace_in, "%f", &read_float );
  3215.  
  3216.                     if ( flag != 1 )
  3217.                     {
  3218.                         printf( "Error Parsing Event Record\n" );
  3219.  
  3220.                         trc_find_event_end( ID );
  3221.  
  3222.                         return( TRC_FALSE );
  3223.                     }
  3224.  
  3225.                     TRC_ARR_VALUE_OF( trptr->value, float, i ) =
  3226.                         read_float;
  3227.  
  3228.                     if ( i < num - 1 )
  3229.                     {
  3230.                         if ( !trc_find_event_str( ID, "," ) )
  3231.                             return( TRC_FALSE );
  3232.                     }
  3233.                 }
  3234.  
  3235.                 break;
  3236.             }
  3237.  
  3238.             case TEV_DATA_DCPLX:
  3239.             case TEV_DATA_DOUBLE:
  3240.             {
  3241.                 for ( i=0 ; i < num ; i++ )
  3242.                 {
  3243.                     flag = fscanf( ID->trace_in, "%lf", &read_double );
  3244.  
  3245.                     if ( flag != 1 )
  3246.                     {
  3247.                         printf( "Error Parsing Event Record\n" );
  3248.  
  3249.                         trc_find_event_end( ID );
  3250.  
  3251.                         return( TRC_FALSE );
  3252.                     }
  3253.  
  3254.                     TRC_ARR_VALUE_OF( trptr->value, double, i ) =
  3255.                         read_double;
  3256.  
  3257.                     if ( i < num - 1 )
  3258.                     {
  3259.                         if ( !trc_find_event_str( ID, "," ) )
  3260.                             return( TRC_FALSE );
  3261.                     }
  3262.                 }
  3263.  
  3264.                 break;
  3265.             }
  3266.  
  3267.             case TEV_DATA_INT:
  3268.             {
  3269.                 for ( i=0 ; i < num ; i++ )
  3270.                 {
  3271.                     flag = fscanf( ID->trace_in, "%d", &read_int );
  3272.  
  3273.                     if ( flag != 1 )
  3274.                     {
  3275.                         printf( "Error Parsing Event Record\n" );
  3276.  
  3277.                         trc_find_event_end( ID );
  3278.  
  3279.                         return( TRC_FALSE );
  3280.                     }
  3281.  
  3282.                     TRC_ARR_VALUE_OF( trptr->value, int, i ) = read_int;
  3283.  
  3284.                     if ( i < num - 1 )
  3285.                     {
  3286.                         if ( !trc_find_event_str( ID, "," ) )
  3287.                             return( TRC_FALSE );
  3288.                     }
  3289.                 }
  3290.  
  3291.                 break;
  3292.             }
  3293.  
  3294.             case TEV_DATA_UINT:
  3295.             {
  3296.                 for ( i=0 ; i < num ; i++ )
  3297.                 {
  3298.                     flag = fscanf( ID->trace_in, "%u", &read_int );
  3299.  
  3300.                     if ( flag != 1 )
  3301.                     {
  3302.                         printf( "Error Parsing Event Record\n" );
  3303.  
  3304.                         trc_find_event_end( ID );
  3305.  
  3306.                         return( TRC_FALSE );
  3307.                     }
  3308.  
  3309.                     TRC_ARR_VALUE_OF( trptr->value, int, i ) = read_int;
  3310.  
  3311.                     if ( i < num - 1 )
  3312.                     {
  3313.                         if ( !trc_find_event_str( ID, "," ) )
  3314.                             return( TRC_FALSE );
  3315.                     }
  3316.                 }
  3317.  
  3318.                 break;
  3319.             }
  3320.  
  3321.             case TEV_DATA_LONG:
  3322.             case TEV_DATA_ULONG:
  3323.             {
  3324.                 for ( i=0 ; i < num ; i++ )
  3325.                 {
  3326.                     flag = fscanf( ID->trace_in, "%ld", &read_long );
  3327.  
  3328.                     if ( flag != 1 )
  3329.                     {
  3330.                         printf( "Error Parsing Event Record\n" );
  3331.  
  3332.                         trc_find_event_end( ID );
  3333.  
  3334.                         return( TRC_FALSE );
  3335.                     }
  3336.  
  3337.                     TRC_ARR_VALUE_OF( trptr->value, long, i ) =
  3338.                         read_long;
  3339.  
  3340.                     if ( i < num - 1 )
  3341.                     {
  3342.                         if ( !trc_find_event_str( ID, "," ) )
  3343.                             return( TRC_FALSE );
  3344.                     }
  3345.                 }
  3346.  
  3347.                 break;
  3348.             }
  3349.  
  3350.             case TEV_DATA_SHORT:
  3351.             {
  3352.                 for ( i=0 ; i < num ; i++ )
  3353.                 {
  3354.                     flag = fscanf( ID->trace_in, "%d", &read_short );
  3355.  
  3356.                     if ( flag != 1 )
  3357.                     {
  3358.                         printf( "Error Parsing Event Record\n" );
  3359.  
  3360.                         trc_find_event_end( ID );
  3361.  
  3362.                         return( TRC_FALSE );
  3363.                     }
  3364.  
  3365.                     TRC_ARR_VALUE_OF( trptr->value, short, i ) =
  3366.                         read_short;
  3367.  
  3368.                     if ( i < num - 1 )
  3369.                     {
  3370.                         if ( !trc_find_event_str( ID, "," ) )
  3371.                             return( TRC_FALSE );
  3372.                     }
  3373.                 }
  3374.  
  3375.                 break;
  3376.             }
  3377.  
  3378.             case TEV_DATA_USHORT:
  3379.             {
  3380.                 for ( i=0 ; i < num ; i++ )
  3381.                 {
  3382.                     flag = fscanf( ID->trace_in, "%u", &read_short );
  3383.  
  3384.                     if ( flag != 1 )
  3385.                     {
  3386.                         printf( "Error Parsing Event Record\n" );
  3387.  
  3388.                         trc_find_event_end( ID );
  3389.  
  3390.                         return( TRC_FALSE );
  3391.                     }
  3392.  
  3393.                     TRC_ARR_VALUE_OF( trptr->value, short, i ) =
  3394.                         read_short;
  3395.  
  3396.                     if ( i < num - 1 )
  3397.                     {
  3398.                         if ( !trc_find_event_str( ID, "," ) )
  3399.                             return( TRC_FALSE );
  3400.                     }
  3401.                 }
  3402.  
  3403.                 break;
  3404.             }
  3405.  
  3406.             case TEV_DATA_STRING:
  3407.             {
  3408.                 if ( DD->array == TEV_DATA_SCALAR )
  3409.                 {
  3410.                     if ( !trc_find_event_str( ID, "{" ) )
  3411.                         return( TRC_FALSE );
  3412.                 }
  3413.  
  3414.                 for ( i=0 ; i < num ; i++ )
  3415.                 {
  3416.                     if ( !trc_find_event_str( ID, "\"" ) )
  3417.                         return( TRC_FALSE );
  3418.  
  3419.                     j = 0;
  3420.  
  3421.                     while ( (c = getc( ID->trace_in )) != (char) EOF
  3422.                         && c != '"' )
  3423.                     {
  3424.                         read_str[j++] = c;
  3425.                     }
  3426.  
  3427.                     TRC_CKEOF( c, "EOF Parsing Event Record\n",
  3428.                         return( TRC_FALSE ) );
  3429.  
  3430.                     read_str[j] = '\0';
  3431.  
  3432.                     TRC_ARR_VALUE_OF( trptr->value, char *, i ) =
  3433.                         trc_copy_str( read_str );
  3434.  
  3435.                     if ( i < num - 1 )
  3436.                     {
  3437.                         if ( !trc_find_event_str( ID, "," ) )
  3438.                             return( TRC_FALSE );
  3439.                     }
  3440.                 }
  3441.  
  3442.                 if ( DD->array == TEV_DATA_SCALAR )
  3443.                 {
  3444.                     if ( !trc_find_event_str( ID, "}" ) )
  3445.                         return( TRC_FALSE );
  3446.                 }
  3447.  
  3448.                 break;
  3449.             }
  3450.  
  3451.             case TEV_DATA_STRUCT_START:
  3452.             case TEV_DATA_STRUCT_END:
  3453.             case TEV_DATA_DEFERRED:
  3454.             {
  3455.                 printf( "DT Not Impl\n" );
  3456.  
  3457.                 trc_find_event_end( ID );
  3458.  
  3459.                 return( TRC_FALSE );
  3460.             }
  3461.  
  3462.             default:
  3463.             {
  3464.                 printf( "DT Unknown\n" );
  3465.  
  3466.                 trc_find_event_end( ID );
  3467.  
  3468.                 return( TRC_FALSE );
  3469.             }
  3470.         }
  3471.  
  3472.         if ( DD->array == TEV_DATA_ARRAY )
  3473.         {
  3474.             /* matching { */
  3475.  
  3476.             if ( !trc_find_event_str( ID, "}" ) )
  3477.                 return( TRC_FALSE );
  3478.         }
  3479.  
  3480.         if ( DD->next != NULL )
  3481.         {
  3482.             if ( !trc_find_event_str( ID, "," ) )
  3483.                 return( TRC_FALSE );
  3484.         }
  3485.  
  3486.         DD = DD->next;
  3487.     }
  3488.  
  3489.     (ID->handle_event)( ID, TD, TR );
  3490.  
  3491.     trc_free_tevrec( &TR );
  3492.  
  3493.     return( TRC_TRUE );
  3494. }
  3495.  
  3496.  
  3497. int
  3498. trc_find_event_str_ret( ID, str, retstr, retlen )
  3499. TRC_ID ID;
  3500. char *str;
  3501. char *retstr;
  3502. int retlen;
  3503. {
  3504.     char tmp[1024];
  3505.  
  3506.     char c;
  3507.  
  3508.     int index;
  3509.     int i, j;
  3510.     int nope;
  3511.     int len;
  3512.     int r;
  3513.  
  3514.     len = strlen( str );
  3515.  
  3516.     for ( i=0 ; i < len ; i++ )
  3517.         tmp[i] = '\0';
  3518.  
  3519.     r = 0;
  3520.  
  3521.     i = 0;
  3522.  
  3523.     while ( (c = getc( ID->trace_in )) != (char) EOF )
  3524.     {
  3525.         if ( retstr && r < retlen - 1 )
  3526.             retstr[r++] = c;
  3527.  
  3528.         tmp[i] = c;
  3529.  
  3530.         nope = 0;
  3531.  
  3532.         for ( j=0 ; j < len && !nope ; j++ )
  3533.         {
  3534.             index = i - len + j + 1;
  3535.  
  3536.             index = index < 0 ? index + len : index;
  3537.  
  3538.             if ( tmp[index] != str[j] )
  3539.                 nope++;
  3540.         }
  3541.  
  3542.         if ( !nope )
  3543.         {
  3544.             if ( retstr )
  3545.                 retstr[r] = '\0';
  3546.  
  3547.             return( TRC_TRUE );
  3548.         }
  3549.  
  3550.         i = ( i + 1 ) % len;
  3551.     }
  3552.  
  3553.     printf( "EOF Reading Trace File - \"%s\" not found.\n", str );
  3554.  
  3555.     if ( retstr )
  3556.         retstr[r] = '\0';
  3557.  
  3558.     return( TRC_FALSE );
  3559. }
  3560.  
  3561.  
  3562. int
  3563. trc_find_event_str( ID, str )
  3564. TRC_ID ID;
  3565. char *str;
  3566. {
  3567.     return( trc_find_event_str_ret( ID, str, (char *) NULL, 0 ) );
  3568. }
  3569.  
  3570.  
  3571. int
  3572. trc_find_event_end_ret( ID, retstr, retlen )
  3573. TRC_ID ID;
  3574. char *retstr;
  3575. int retlen;
  3576. {
  3577.     return( trc_find_event_str_ret( ID, ";;", retstr, retlen ) );
  3578. }
  3579.  
  3580.  
  3581. int
  3582. trc_find_event_end( ID )
  3583. TRC_ID ID;
  3584. {
  3585.     return( trc_find_event_end_ret( ID, (char *) NULL, 0 ) );
  3586. }
  3587.  
  3588.